├── .gitattributes ├── .gitignore ├── Assy ├── OIS.cs └── WorkSlip.cs ├── EightBits.cs ├── Properties └── AssemblyInfo.cs ├── SecsGem ├── CEID.cs ├── CodeFile_Enums.cs ├── CodeFile_EventArgs.cs ├── DefineReport.xml ├── Drivers │ ├── HsmsCodeFile.cs │ ├── HsmsDriver.cs │ ├── SecsDriverBase.cs │ └── SecsIDriver.cs ├── EquipmentModel.cs ├── FormatCodeHelper.cs ├── GemOption.cs ├── HsmsHost.cs ├── HsmsParameters.cs ├── MapData_E142.cs ├── ReportVariable.cs ├── ReportVariableCollection.cs ├── SVIDAttribute.cs ├── SVIDAttributeMapper.cs ├── SecsDataItem.cs ├── SecsHost.cs ├── SecsHostFactory.cs ├── SecsIHost.cs ├── SecsIIMessageParser.cs ├── SecsIMessageParser.cs ├── SecsIParameters.cs ├── SecsItem.cs ├── SecsItemAscii.cs ├── SecsItemBinary.cs ├── SecsItemBoolean.cs ├── SecsItemF4.cs ├── SecsItemF8.cs ├── SecsItemFactory.cs ├── SecsItemI1.cs ├── SecsItemI2.cs ├── SecsItemI4.cs ├── SecsItemI8.cs ├── SecsItemList.cs ├── SecsItemManager.cs ├── SecsItemMultiByteChar.cs ├── SecsItemU1.cs ├── SecsItemU2.cs ├── SecsItemU4.cs ├── SecsItemU8.cs ├── SecsMessage.cs ├── SecsMessageBase.cs ├── SecsMessageParserBase.cs ├── SecsReport.cs ├── SecsTransaction.cs ├── SmlBuilder.cs ├── StatusVariable.cs └── T3Timer.cs ├── Threading └── TimedLock.cs ├── XtraLibrary.csproj ├── XtraLibrary.sln └── app.config /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc -------------------------------------------------------------------------------- /Assy/OIS.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace XtraLibrary.Assy 6 | { 7 | public class OIS 8 | { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /Assy/WorkSlip.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace XtraLibrary.Assy 6 | { 7 | public class WorkSlip 8 | { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /EightBits.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary 7 | { 8 | 9 | public class EightBits 10 | { 11 | private byte[] m_Bits; 12 | 13 | public EightBits() { 14 | m_Bits = new byte[8]; 15 | } 16 | 17 | public EightBits(byte b) 18 | :this() 19 | { 20 | byte val = b; 21 | for (int i = 0; i < m_Bits.Length; i++) 22 | { 23 | m_Bits[i] = (byte)(val & 0x01); 24 | val = (byte)(val >> 1); 25 | } 26 | } 27 | 28 | public byte ToByte() 29 | { 30 | byte b = 0; 31 | for (int i = m_Bits.Length - 1; i >= 0; i--) 32 | { 33 | b = (byte)(b << 1); 34 | b += m_Bits[i]; 35 | } 36 | return b; 37 | } 38 | 39 | public byte Bit1 40 | { 41 | get 42 | { 43 | return m_Bits[0]; 44 | } 45 | set 46 | { 47 | if (value > 1) 48 | { 49 | throw new OverflowException("value should be 0 or 1"); 50 | } 51 | m_Bits[0] = value; 52 | } 53 | } 54 | 55 | public byte Bit2 56 | { 57 | get 58 | { 59 | return m_Bits[1]; 60 | } 61 | set 62 | { 63 | if (value > 1) 64 | { 65 | throw new OverflowException("value should be 0 or 1"); 66 | } 67 | m_Bits[1] = value; 68 | } 69 | } 70 | 71 | public byte Bit3 72 | { 73 | get 74 | { 75 | return m_Bits[2]; 76 | } 77 | set 78 | { 79 | if (value > 1) 80 | { 81 | throw new OverflowException("value should be 0 or 1"); 82 | } 83 | m_Bits[2] = value; 84 | } 85 | } 86 | 87 | public byte Bit4 88 | { 89 | get 90 | { 91 | return m_Bits[3]; 92 | } 93 | set 94 | { 95 | if (value > 1) 96 | { 97 | throw new OverflowException("value should be 0 or 1"); 98 | } 99 | m_Bits[3] = value; 100 | } 101 | } 102 | 103 | public byte Bit5 104 | { 105 | get 106 | { 107 | return m_Bits[4]; 108 | } 109 | set 110 | { 111 | if (value > 1) 112 | { 113 | throw new OverflowException("value should be 0 or 1"); 114 | } 115 | m_Bits[4] = value; 116 | } 117 | } 118 | 119 | public byte Bit6 120 | { 121 | get 122 | { 123 | return m_Bits[5]; 124 | } 125 | set 126 | { 127 | if (value > 1) 128 | { 129 | throw new OverflowException("value should be 0 or 1"); 130 | } 131 | m_Bits[5] = value; 132 | } 133 | } 134 | 135 | public byte Bit7 136 | { 137 | get 138 | { 139 | return m_Bits[6]; 140 | } 141 | set 142 | { 143 | if (value > 1) 144 | { 145 | throw new OverflowException("value should be 0 or 1"); 146 | } 147 | m_Bits[6] = value; 148 | } 149 | } 150 | 151 | public byte Bit8 152 | { 153 | get 154 | { 155 | return m_Bits[7]; 156 | } 157 | set 158 | { 159 | if (value > 1) 160 | { 161 | throw new OverflowException("value should be 0 or 1"); 162 | } 163 | m_Bits[7] = value; 164 | } 165 | } 166 | 167 | public override string ToString() 168 | { 169 | string ret = null; 170 | for (int i = m_Bits.Length - 1; i >= 0; i--) 171 | { 172 | ret += m_Bits[i].ToString(); 173 | } 174 | return ret; 175 | } 176 | 177 | public static explicit operator byte (EightBits eb) 178 | { 179 | return eb.ToByte(); 180 | } 181 | 182 | public static explicit operator EightBits(byte b) 183 | { 184 | return new EightBits(b); 185 | } 186 | 187 | } 188 | } 189 | -------------------------------------------------------------------------------- /Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("XtraLibrary")] 9 | [assembly: AssemblyDescription("XtraLibrary 17.09.21.001")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("LSI-ROHM")] 12 | [assembly: AssemblyProduct("XtraLibrary")] 13 | [assembly: AssemblyCopyright("Copyright © LSI-ROHM 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("99b17790-2c24-4c62-80b4-23c49897e38b")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /SecsGem/CEID.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class CEID 9 | { 10 | public void AddReport(ReportVariable report) 11 | { 12 | 13 | } 14 | } 15 | public class CEID 16 | : CEID where T : SecsItem 17 | { 18 | //POSIBLE TYPES OF CEID are 19 | //ASCII, I1, I2, I4, I8, U1, U2, U4, U8 20 | //reference document :141433-E005-00-0712.pdf 21 | 22 | 23 | 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /SecsGem/CodeFile_Enums.cs: -------------------------------------------------------------------------------- 1 | namespace XtraLibrary.SecsGem 2 | { 3 | public enum GemProtocol 4 | { 5 | SECS_I = 0, 6 | HSMS = 1 7 | } 8 | 9 | public enum HsmsConnectProcedure 10 | { 11 | PASSIVE = 0, 12 | ACTIVE = 1 13 | } 14 | 15 | public enum HsmsState 16 | { 17 | NOT_CONNECTED = 0, 18 | NOT_SELECTED = 1, 19 | SELECTED = 2 20 | } 21 | 22 | public enum SType : byte 23 | { 24 | Message = 0, 25 | SelectReq = 1, 26 | SelectResp = 2, 27 | LinktestReq = 5, 28 | LinktestResp = 6, 29 | SeparateReq = 9 30 | } 31 | 32 | /// 33 | /// Bit 876543 of format code byte 34 | /// 35 | public enum FormatCode : byte 36 | { 37 | /// 38 | /// LIST (length in elements) 39 | /// 40 | LIST = 0, 41 | 42 | /// 43 | /// Binary 44 | /// 45 | Binary = 8, 46 | 47 | /// 48 | /// Boolean 49 | /// 50 | Boolean = 9, 51 | 52 | /// 53 | /// ASCII : Non-printing characters are equipment-specific 54 | /// 55 | ASCII = 16, 56 | 57 | /// 58 | /// JIS-8 59 | /// 60 | JIS8 = 17, 61 | 62 | /// 63 | /// Multi-byte charactor 64 | /// 65 | MC = 18, 66 | 67 | /// 68 | /// 8-byte integer (signed) 69 | /// 70 | I8 = 24, 71 | 72 | /// 73 | /// 1-byte integer (signed) 74 | /// 75 | I1 = 25, 76 | 77 | /// 78 | /// 2-byte integer (signed) 79 | /// 80 | I2 = 26, 81 | 82 | /// 83 | /// 4-byte integer (signed) 84 | /// 85 | I4 = 28, 86 | 87 | /// 88 | /// 8-byte floating poing 89 | /// 90 | F8 = 32, 91 | 92 | /// 93 | /// 4-byte floating poing 94 | /// 95 | F4 = 36, 96 | 97 | /// 98 | /// 8-byte integer (unsigned) 99 | /// 100 | U8 = 40, 101 | 102 | /// 103 | /// 1-byte integer (unsigned) 104 | /// 105 | U1 = 41, 106 | 107 | /// 108 | /// 2-byte integer (unsigned) 109 | /// 110 | U2 = 42, 111 | 112 | /// 113 | /// 4-byte integer (unsigned) 114 | /// 115 | U4 = 44 116 | } 117 | 118 | public enum CategoryOfMessage :byte 119 | { 120 | NotUse = 0, 121 | EquipmentStatus = 1, 122 | EquipmentControlAndDiagnostics = 2, 123 | MaterialsStatus = 3, 124 | MaterialControl = 4, 125 | ExceptionHandling = 5, 126 | DataCollection = 6, 127 | ProcessProgramManagement = 7, 128 | ControlProgramTransfer = 8, 129 | SystemError = 9, 130 | TerminalService = 10, 131 | HostFileService = 11, 132 | WaferMapping = 12, 133 | DataSetTransafer = 13, 134 | ObjectServices = 14, 135 | RecipeManagement = 15, 136 | ProcessingManagement = 16, 137 | EquipmentControlAndDiagnostics_2 = 17, 138 | SubSystemControlAndData = 18, 139 | RecipeAndParameterManagement = 19 140 | 141 | } 142 | 143 | public enum DirectionType 144 | { 145 | Sent = 0, 146 | Recv = 1 147 | } 148 | } -------------------------------------------------------------------------------- /SecsGem/CodeFile_EventArgs.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace XtraLibrary.SecsGem 4 | { 5 | public sealed class PrimarySecsMessageEventArgs 6 | { 7 | 8 | private SecsMessageBase m_Primary; 9 | public SecsMessageBase Primary 10 | { 11 | get 12 | { 13 | return m_Primary; 14 | } 15 | } 16 | 17 | internal PrimarySecsMessageEventArgs(SecsMessageBase priMsg) 18 | { 19 | m_Primary = priMsg; 20 | } 21 | } 22 | 23 | public delegate void PrimarySecsMessageEventHandler(object sender, PrimarySecsMessageEventArgs e); 24 | 25 | public sealed class SecondarySecsMessageEventArgs 26 | { 27 | private SecsMessageBase m_Primary; 28 | public SecsMessageBase Primary 29 | { 30 | get 31 | { 32 | return m_Primary; 33 | } 34 | } 35 | 36 | private SecsMessageBase m_Secondary; 37 | public SecsMessageBase Secondary 38 | { 39 | get 40 | { 41 | return m_Secondary; 42 | } 43 | } 44 | 45 | internal SecondarySecsMessageEventArgs(SecsMessageBase priMsg, SecsMessageBase secMsg) 46 | { 47 | m_Primary = priMsg; 48 | m_Secondary = secMsg; 49 | } 50 | } 51 | 52 | public delegate void SecondarySecsMessageEventHandler(object sender, SecondarySecsMessageEventArgs e); 53 | 54 | public sealed class TraceLogEventArgs 55 | { 56 | private string m_SML; 57 | public string SML 58 | { 59 | get 60 | { 61 | return m_SML; 62 | } 63 | } 64 | 65 | private DirectionType m_Direction; 66 | public DirectionType Direction 67 | { 68 | get { 69 | return m_Direction; 70 | } 71 | } 72 | 73 | private DateTime m_TimeStamp; 74 | 75 | public DateTime TimeStamp 76 | { 77 | get { 78 | return m_TimeStamp; 79 | } 80 | } 81 | 82 | private string m_LogMessage; 83 | public string LogMessage 84 | { 85 | get { 86 | return m_LogMessage; 87 | } 88 | } 89 | 90 | internal TraceLogEventArgs(DateTime timeStamp, string strSml, DirectionType direct, string logMsg) 91 | { 92 | m_TimeStamp = timeStamp; 93 | m_SML = strSml; 94 | m_Direction = direct; 95 | m_LogMessage = logMsg; 96 | } 97 | 98 | } 99 | 100 | public delegate void TraceLogEventHandler(object sender, TraceLogEventArgs e); 101 | 102 | public sealed class EventReportReceivedEventArgs 103 | { 104 | internal EventReportReceivedEventArgs() 105 | { 106 | 107 | } 108 | } 109 | 110 | public delegate void EventReportReceivedEventHandler(object sender, EventReportReceivedEventArgs e); 111 | 112 | public sealed class SecsErrorNotificationEventArgs 113 | { 114 | 115 | private string m_Message; 116 | 117 | public string Message 118 | { 119 | get { 120 | return m_Message; 121 | } 122 | } 123 | 124 | private uint m_TransactionId; 125 | 126 | public uint TransactionId 127 | { 128 | get { 129 | return m_TransactionId; 130 | } 131 | } 132 | 133 | private SecsMessageBase m_Source; 134 | 135 | public SecsMessageBase Source 136 | { 137 | get { 138 | return m_Source; 139 | } 140 | } 141 | 142 | internal SecsErrorNotificationEventArgs(string errMessage, SecsMessageBase msg) 143 | :this(errMessage, msg.TransactionId) 144 | { 145 | m_Source = msg; 146 | } 147 | 148 | internal SecsErrorNotificationEventArgs(string errMessage, uint tid) 149 | { 150 | m_Message = errMessage; 151 | m_TransactionId = tid; 152 | } 153 | } 154 | 155 | public delegate void SecsErrorNotificationEventHandler(object sender, SecsErrorNotificationEventArgs e); 156 | 157 | //public class AlarmReportReceivedEventArgs 158 | //{ 159 | // private SecsMessageBase m_S5F1; 160 | // public SecsMessageBase S5F1 161 | // { 162 | // get { 163 | // return m_S5F1; 164 | // } 165 | // } 166 | 167 | // internal AlarmReportReceivedEventArgs(SecsMessageBase msg) 168 | // { 169 | // m_S5F1 = msg; 170 | // } 171 | //} 172 | 173 | //public delegate void AlarmReportReceivedEventHandler(object sender, AlarmReportReceivedEventArgs e); 174 | 175 | public class ConversionErrorEventArgs 176 | { 177 | private Exception m_Exception; 178 | public Exception Exception 179 | { 180 | get { 181 | return m_Exception; 182 | } 183 | } 184 | 185 | private byte[] m_Data; 186 | public byte[] Data 187 | { 188 | get { 189 | return m_Data; 190 | } 191 | } 192 | 193 | internal ConversionErrorEventArgs(Exception ex, byte[] data) 194 | { 195 | m_Exception = ex; 196 | m_Data = data; 197 | } 198 | } 199 | 200 | public delegate void ConversionErrorEventHandler(object sender, ConversionErrorEventArgs e); 201 | 202 | public class HsmsStateChangedEventArgs 203 | { 204 | private HsmsState m_State; 205 | 206 | public HsmsState State 207 | { 208 | get { 209 | return m_State; 210 | } 211 | } 212 | 213 | internal HsmsStateChangedEventArgs(HsmsState newState) 214 | { 215 | m_State = newState; 216 | } 217 | } 218 | 219 | public delegate void HsmsStateChangedEventHandler(object sender, HsmsStateChangedEventArgs e); 220 | 221 | public class SecsIConnectionChangedEventArgs 222 | { 223 | private bool m_Connected; 224 | public bool Connected 225 | { 226 | get { 227 | return m_Connected; 228 | } 229 | } 230 | 231 | internal SecsIConnectionChangedEventArgs(bool isConnected) 232 | { 233 | m_Connected = isConnected; 234 | } 235 | } 236 | 237 | public delegate void SecsIConnectionChangedEventHandler(object sender, SecsIConnectionChangedEventArgs e); 238 | } -------------------------------------------------------------------------------- /SecsGem/DefineReport.xml: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /SecsGem/Drivers/HsmsCodeFile.cs: -------------------------------------------------------------------------------- 1 | namespace XtraLibrary.SecsGem.Drivers 2 | { 3 | public enum HsmsConnectProcedure 4 | { 5 | PASSIVE = 0, 6 | ACTIVE = 1 7 | } 8 | 9 | public enum HsmsState 10 | { 11 | NOT_CONNECTED = 0, 12 | NOT_SELECTED = 1, 13 | SELECTED = 2 14 | } 15 | 16 | public enum SType :byte 17 | { 18 | Message = 0, 19 | SelectReq = 1, 20 | SelectResp = 2, 21 | LinktestReq = 5, 22 | LinktestResp = 6, 23 | SeparateReq = 9 24 | } 25 | 26 | public enum SecsIContentionType 27 | { 28 | Slave = 0, 29 | Master = 1 30 | } 31 | } -------------------------------------------------------------------------------- /SecsGem/Drivers/SecsDriverBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | using System.Threading; 6 | 7 | namespace XtraLibrary.SecsGem.Drivers 8 | { 9 | public abstract class SecsDriverBase 10 | { 11 | public event PrimarySecsMessageEventHandler ReceivedPrimaryMessage; 12 | public event SecondarySecsMessageEventHandler ReceivedSecondaryMessage; 13 | //public event SecondarySecsMessageEventHandler SentMessage; 14 | public event TraceLogEventHandler TraceLog; 15 | 16 | private SmlBuilder m_SmlBuilder; 17 | 18 | private ushort m_DeviceId; 19 | public ushort DeviceId 20 | { 21 | get 22 | { 23 | return m_DeviceId; 24 | } 25 | set 26 | { 27 | m_DeviceId = value; 28 | } 29 | } 30 | 31 | private uint m_TransactionId; 32 | 33 | protected SynchronizationContext m_SyncContext; 34 | private SecsMessageParserBase m_MsgParser; 35 | 36 | protected SecsDriverBase(SecsMessageParserBase parser) { 37 | m_TransactionId = 0; 38 | m_DeviceId = 0; 39 | m_SyncContext = SynchronizationContext.Current; 40 | if (m_SyncContext == null) 41 | { 42 | m_SyncContext = new SynchronizationContext(); 43 | } 44 | m_MsgParser = parser; 45 | m_SmlBuilder = new SmlBuilder(); 46 | } 47 | 48 | public void Send(SecsMessageBase msg) 49 | { 50 | msg.DeviceId = m_DeviceId; 51 | bool isPrimary = ((msg.Function & 0x01) == 0x01); 52 | 53 | if (isPrimary) //primary message 54 | { 55 | msg.TransactionId = GetNextTransactionId(); 56 | OnSendingPrimaryMessage(msg); 57 | } 58 | //should try { } catch {} for error 59 | byte[] data = m_MsgParser.GetBytes(msg); 60 | 61 | SendBytes(data); 62 | //RaiseEventSend(msg); 63 | TraceSmlLog(DateTime.Now, msg, TraceLogEventArgs.DirectionType.Sent); 64 | } 65 | 66 | protected abstract void OnSendingPrimaryMessage(SecsMessageBase msg); 67 | 68 | protected abstract void SendBytes(byte[] data); 69 | 70 | public abstract void Start(); 71 | public abstract void Stop(); 72 | 73 | protected uint GetNextTransactionId() 74 | { 75 | lock (this) 76 | { 77 | if (m_TransactionId == uint.MaxValue) 78 | { 79 | m_TransactionId = 1; 80 | } 81 | else 82 | { 83 | m_TransactionId += 1; 84 | } 85 | } 86 | 87 | return m_TransactionId; 88 | } 89 | 90 | #region "Raise Events" 91 | 92 | protected void RaiseEventReceivedPrimaryMessage(SecsMessageBase primary) 93 | { 94 | if (ReceivedPrimaryMessage != null) 95 | { 96 | m_SyncContext.Post(Post_Event_ReceivedPrimaryMessage, new PrimarySecsMessageEventArgs(primary)); 97 | } 98 | } 99 | 100 | private void Post_Event_ReceivedPrimaryMessage(object state) 101 | { 102 | 103 | PrimarySecsMessageEventArgs e = (PrimarySecsMessageEventArgs)state; 104 | ReceivedPrimaryMessage(this, e); 105 | 106 | } 107 | 108 | protected void RaiseEventReceivedSecondaryMessage(SecsMessageBase primary, SecsMessageBase secondary) 109 | { 110 | if (ReceivedSecondaryMessage != null) 111 | { 112 | m_SyncContext.Post(Post_Event_ReceivedSecondaryMessage, new SecondarySecsMessageEventArgs(primary, secondary)); 113 | } 114 | } 115 | 116 | private void Post_Event_ReceivedSecondaryMessage(object state) 117 | { 118 | SecondarySecsMessageEventArgs e = (SecondarySecsMessageEventArgs)state; 119 | ReceivedSecondaryMessage(this, e); 120 | } 121 | 122 | protected void RaiseEventTraceLog(DateTime timeStamp, string strSml, TraceLogEventArgs.DirectionType direction) 123 | { 124 | if (TraceLog != null) 125 | { 126 | m_SyncContext.Post(Post_Evemt_TraceLog, new TraceLogEventArgs(timeStamp, strSml, direction)); 127 | } 128 | } 129 | 130 | private void Post_Evemt_TraceLog(object state) 131 | { 132 | TraceLogEventArgs e = (TraceLogEventArgs)state; 133 | TraceLog(this, e); 134 | } 135 | 136 | 137 | #endregion 138 | 139 | private void TraceSmlLog(DateTime timeStamp, SecsMessageBase msg, TraceLogEventArgs.DirectionType direct) 140 | { 141 | string strSml = m_SmlBuilder.ToSmlString(msg); 142 | //keep log to file 143 | 144 | //fire event 145 | RaiseEventTraceLog(timeStamp, strSml, direct); 146 | } 147 | } 148 | } 149 | -------------------------------------------------------------------------------- /SecsGem/EquipmentModel.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Reflection; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class EquipmentModel 9 | { 10 | private string m_Name; 11 | private GemOption m_Connection; 12 | 13 | public EquipmentModel(string eqName) 14 | { 15 | m_Connection = new GemOption(); 16 | m_Name = eqName; 17 | } 18 | 19 | #region "Properties" 20 | 21 | public string Name 22 | { 23 | get { 24 | return m_Name; 25 | } 26 | set { 27 | m_Name = value; 28 | } 29 | } 30 | 31 | public GemOption Connection 32 | { 33 | get 34 | { 35 | return m_Connection; 36 | } 37 | set 38 | { 39 | m_Connection = value; 40 | } 41 | } 42 | 43 | #endregion 44 | 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /SecsGem/FormatCodeHelper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class FormatCodeHelper 9 | { 10 | private FormatCodeHelper() { } 11 | 12 | public static FormatCode GetFormatCode(byte formatCodeByte, out byte lengthByteCount){ 13 | 14 | //bit : 8765 4321 15 | //formatCodeByte : 0000 00 16 | //lenght byte : 00 17 | 18 | byte formatCodeVal = (byte)(formatCodeByte >> 2); 19 | 20 | lengthByteCount = (byte)(formatCodeByte & 0x03); //0000 0011 make bit "8764 43" to 0 21 | 22 | if (!Enum.IsDefined(typeof(FormatCode), formatCodeVal)) 23 | { 24 | throw new Exception("Unknow format code :" + formatCodeVal.ToString()); 25 | } 26 | 27 | return (FormatCode)formatCodeVal; 28 | 29 | } 30 | 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SecsGem/GemOption.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class GemOption 9 | { 10 | private ushort m_DeviceId; 11 | private GemProtocol m_Protocol; 12 | private SecsIParameters m_SecsIParameters; 13 | private HsmsParameters m_HsmsParameters; 14 | 15 | public GemOption() { 16 | m_DeviceId = 0; 17 | m_Protocol = GemProtocol.HSMS; 18 | } 19 | 20 | public ushort DeviceId 21 | { 22 | get { 23 | return m_DeviceId; 24 | } 25 | set 26 | { 27 | m_DeviceId = value; 28 | } 29 | } 30 | 31 | public GemProtocol Protocol 32 | { 33 | get 34 | { 35 | return m_Protocol; 36 | } 37 | set { 38 | m_Protocol = value; 39 | } 40 | } 41 | 42 | public SecsIParameters SecsIParameters 43 | { 44 | get 45 | { 46 | return m_SecsIParameters; 47 | } 48 | set { 49 | m_SecsIParameters = value; 50 | } 51 | } 52 | 53 | public HsmsParameters HsmsParameters 54 | { 55 | get { 56 | return m_HsmsParameters; 57 | } 58 | set { 59 | m_HsmsParameters = value; 60 | } 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /SecsGem/HsmsParameters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class HsmsParameters 9 | { 10 | private int m_T3_Interval; 11 | private int m_T5_Interval; 12 | private int m_T6_Interval; 13 | private int m_T7_Interval; 14 | private int m_T8_Interval; 15 | private int m_Linktest_Interval; 16 | private bool m_LinktestEnabled; 17 | 18 | private string m_IPAddress; 19 | private int m_PortNo; 20 | 21 | private HsmsConnectProcedure m_Mode; 22 | 23 | public HsmsParameters() 24 | { 25 | m_Mode = HsmsConnectProcedure.ACTIVE; 26 | m_IPAddress = "127.0.0.1"; 27 | m_PortNo = 5040; 28 | 29 | m_T3_Interval = 45; 30 | m_T5_Interval = 10; 31 | m_T6_Interval = 5; 32 | m_T7_Interval = 10; 33 | m_T8_Interval = 5; 34 | m_Linktest_Interval = 10; 35 | m_LinktestEnabled = true; 36 | } 37 | 38 | public int T3_Interval 39 | { 40 | get 41 | { 42 | return m_T3_Interval; 43 | } 44 | set 45 | { 46 | if (value < 1 || value > 120) 47 | { 48 | throw new Exception("Value is out of range 1 - 120 secs"); 49 | } 50 | m_T3_Interval = value; 51 | } 52 | } 53 | 54 | public int T5_Interval 55 | { 56 | get 57 | { 58 | return m_T5_Interval; 59 | } 60 | set 61 | { 62 | if (value < 1 || value > 240) 63 | { 64 | throw new Exception("Value is out of range 1 - 240 secs"); 65 | } 66 | m_T5_Interval = value; 67 | } 68 | } 69 | 70 | public int T6_Interval 71 | { 72 | get 73 | { 74 | return m_T6_Interval; 75 | } 76 | set 77 | { 78 | if (value < 1 || value > 240) 79 | { 80 | throw new Exception("Value is out of range 1 - 240 secs"); 81 | } 82 | m_T6_Interval = value; 83 | } 84 | } 85 | 86 | public int T7_Interval 87 | { 88 | get 89 | { 90 | return m_T7_Interval; 91 | } 92 | set 93 | { 94 | if (value < 1 || value > 240) 95 | { 96 | throw new Exception("Value is out of range 1 - 240 secs"); 97 | } 98 | m_T7_Interval = value; 99 | } 100 | } 101 | 102 | public int T8_Interval 103 | { 104 | get 105 | { 106 | return m_T8_Interval; 107 | } 108 | set 109 | { 110 | if (value < 1 || value > 120) 111 | { 112 | throw new Exception("Value is out of range 1 - 240 secs"); 113 | } 114 | m_T8_Interval = value; 115 | } 116 | } 117 | 118 | public int Linktest_Interval 119 | { 120 | get 121 | { 122 | return m_Linktest_Interval; 123 | } 124 | set 125 | { 126 | if (value < 1 || value > 900) 127 | { 128 | throw new Exception("Value is out of range 1 - 900 secs"); 129 | } 130 | m_Linktest_Interval = value; 131 | } 132 | } 133 | 134 | public bool LinktestEnabled 135 | { 136 | get 137 | { 138 | return m_LinktestEnabled; 139 | } 140 | 141 | set 142 | { 143 | m_LinktestEnabled = value; 144 | } 145 | } 146 | 147 | public HsmsConnectProcedure Mode 148 | { 149 | get 150 | { 151 | return m_Mode; 152 | } 153 | set 154 | { 155 | m_Mode = value; 156 | } 157 | } 158 | 159 | public string IPAddress 160 | { 161 | get 162 | { 163 | return m_IPAddress; 164 | } 165 | set 166 | { 167 | m_IPAddress = value; 168 | } 169 | 170 | } 171 | 172 | /// 173 | /// Remote or Local Port 174 | /// 175 | public int PortNo 176 | { 177 | get 178 | { 179 | return m_PortNo; 180 | } 181 | set 182 | { 183 | m_PortNo = value; 184 | } 185 | } 186 | } 187 | } 188 | -------------------------------------------------------------------------------- /SecsGem/MapData_E142.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Xml; 5 | using System.Xml.Serialization; 6 | 7 | namespace XtraLibrary.SecsGem 8 | { 9 | public class MapData_E142 10 | { 11 | #region "Nested Class" 12 | 13 | [XmlElement("Layout")] 14 | public class Layout 15 | { 16 | private string m_ID; 17 | private string m_DefaultUnits; 18 | private bool m_TopLevel; 19 | private ValuePairXY m_Dimension; 20 | private ValuePairXY m_DeviceSize; 21 | private List m_ChildLayoutList; 22 | 23 | [XmlAttribute("LayoutId")] 24 | public string ID 25 | { 26 | get { return m_ID; } 27 | set 28 | { 29 | m_ID = value; 30 | } 31 | } 32 | 33 | [XmlAttribute("DefaultUnits")] 34 | public string DefaultUnits 35 | { 36 | get { return m_DefaultUnits; } 37 | set 38 | { 39 | m_DefaultUnits = value; 40 | } 41 | } 42 | 43 | [XmlAttribute("TopLevel")] 44 | public bool TopLevel 45 | { 46 | get { return m_TopLevel; } 47 | set 48 | { 49 | m_TopLevel = value; 50 | } 51 | } 52 | 53 | [XmlElement("Dimension")] 54 | public ValuePairXY Dimension 55 | { 56 | get { return m_Dimension; } 57 | set 58 | { 59 | m_Dimension = value; 60 | } 61 | } 62 | 63 | [XmlElement("DeviceSize")] 64 | public ValuePairXY DeviceSize 65 | { 66 | get { return m_DeviceSize; } 67 | set 68 | { 69 | m_DeviceSize = value; 70 | } 71 | } 72 | 73 | [XmlElement("ChildLayouts")] 74 | public List ChildLayoutList 75 | { 76 | get { return m_ChildLayoutList; } 77 | set 78 | { 79 | m_ChildLayoutList = value; 80 | } 81 | } 82 | 83 | 84 | } 85 | 86 | [XmlElement("ChildLayout")] 87 | public class ChildLayout 88 | { 89 | public ChildLayout() { } 90 | 91 | private string m_ID; 92 | 93 | [XmlAttribute("LayoutId")] 94 | public string ID 95 | { 96 | get { return m_ID; } 97 | set 98 | { 99 | m_ID = value; 100 | } 101 | } 102 | 103 | } 104 | 105 | public class ValuePairXY 106 | { 107 | public ValuePairXY() { } 108 | 109 | private int m_X; 110 | private int m_Y; 111 | 112 | [XmlAttribute("X")] 113 | public int X 114 | { 115 | get { return m_X; } 116 | set 117 | { 118 | m_X = value; 119 | } 120 | } 121 | 122 | [XmlAttribute("Y")] 123 | public int Y 124 | { 125 | get { return m_Y; } 126 | set 127 | { 128 | m_Y = value; 129 | } 130 | } 131 | 132 | } 133 | 134 | #endregion 135 | 136 | private MapData_E142() { } 137 | 138 | private List m_LayoutList; 139 | 140 | [XmlElement("Layouts")] 141 | public List LayoutList 142 | { 143 | get { return m_LayoutList; } 144 | set 145 | { 146 | m_LayoutList = value; 147 | } 148 | } 149 | 150 | // 151 | // 152 | // 153 | // 154 | // 155 | // 156 | // 157 | // 158 | // 159 | // 160 | // 161 | // 162 | // 163 | // 164 | // 165 | // 166 | // 167 | // 168 | // 169 | // 170 | // 171 | // 172 | // 173 | // 174 | // 175 | // 176 | // 177 | // 178 | // 179 | // 180 | // 181 | // 182 | // 183 | // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 184 | // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 185 | // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 186 | // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 187 | // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 188 | // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 189 | // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 190 | // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 191 | // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 192 | // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 193 | // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 194 | // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 195 | // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 196 | // FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 197 | // 198 | // 199 | // 200 | // 201 | // 202 | 203 | 204 | } 205 | } 206 | -------------------------------------------------------------------------------- /SecsGem/ReportVariable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace XtraLibrary.SecsGem 6 | { 7 | public class ReportVariable 8 | { 9 | protected object m_RPTID; 10 | 11 | public object ID 12 | { 13 | get { 14 | return m_RPTID; 15 | } 16 | } 17 | 18 | internal ReportVariable(object rptId) 19 | { 20 | m_RPTID = rptId; 21 | } 22 | 23 | 24 | } 25 | 26 | public sealed class ReportVariable 27 | :ReportVariable 28 | { 29 | public new RPTID ID 30 | { 31 | get { 32 | return (RPTID)m_RPTID; 33 | } 34 | } 35 | public ReportVariable(RPTID rptId) 36 | : base(rptId) 37 | { 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SecsGem/ReportVariableCollection.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace XtraLibrary.SecsGem 6 | { 7 | public class ReportVariableCollection 8 | { 9 | 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /SecsGem/SVIDAttribute.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Reflection; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | 9 | [AttributeUsage(AttributeTargets.Property, AllowMultiple=false, Inherited=true)] 10 | public class SVIDAttribute 11 | :Attribute 12 | { 13 | private object m_ID; 14 | public object ID 15 | { 16 | get { 17 | return m_ID; 18 | } 19 | } 20 | 21 | private FormatCode m_Format; 22 | public FormatCode Format 23 | { 24 | get { 25 | return m_Format; 26 | } 27 | } 28 | 29 | private int m_Size; 30 | public int Size 31 | { 32 | get { 33 | return m_Size; 34 | } 35 | } 36 | 37 | public const int SIZE_N = -1; 38 | 39 | public SVIDAttribute(FormatCode fc, object svId) 40 | : this(fc, svId, 1) 41 | { 42 | } 43 | 44 | public SVIDAttribute(FormatCode fc, object svId, int size) 45 | { 46 | m_Format = fc; 47 | m_Size = size; 48 | 49 | string strSvid = svId.ToString(); 50 | 51 | switch (fc) 52 | { 53 | case FormatCode.U1: 54 | sbyte u1 = 0; 55 | if (sbyte.TryParse(strSvid, out u1)) 56 | { 57 | m_ID = u1; 58 | } 59 | break; 60 | case FormatCode.U2: 61 | ushort u2 = 0; 62 | if (ushort.TryParse(strSvid, out u2)) 63 | { 64 | m_ID = u2; 65 | } 66 | break; 67 | case FormatCode.U4: 68 | UInt32 u4 = 0; 69 | if (UInt32.TryParse(strSvid, out u4)) 70 | { 71 | m_ID = u4; 72 | } 73 | break; 74 | case FormatCode.U8: 75 | UInt64 u8 = 0; 76 | if (UInt64.TryParse(strSvid, out u8)) 77 | { 78 | m_ID = u8; 79 | } 80 | break; 81 | case FormatCode.I1: 82 | byte i1 = 0; 83 | if (byte.TryParse(strSvid, out i1)) 84 | { 85 | m_ID = i1; 86 | } 87 | break; 88 | case FormatCode.I2: 89 | short i2 = 0; 90 | if (short.TryParse(strSvid, out i2)) 91 | { 92 | m_ID = i2; 93 | } 94 | break; 95 | case FormatCode.I4: 96 | Int32 i4 = 0; 97 | if (Int32.TryParse(strSvid, out i4)) 98 | { 99 | m_ID = i4; 100 | } 101 | break; 102 | case FormatCode.I8: 103 | Int64 i8 = 0; 104 | if (Int64.TryParse(strSvid, out i8)) 105 | { 106 | m_ID = i8; 107 | } 108 | break; 109 | case FormatCode.ASCII: 110 | m_ID = strSvid; 111 | break; 112 | default : 113 | //throw error 114 | throw new Exception("Not supported type " + fc.ToString()); 115 | } 116 | } 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /SecsGem/SVIDAttributeMapper.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Reflection; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public abstract class SVAttributeMapper 9 | { 10 | private EquipmentModel m_Model; 11 | private Dictionary m_SVAttributeDic; 12 | 13 | #region "Netested class" 14 | 15 | private class SVIDMapInfo 16 | { 17 | internal PropertyInfo PropertyInfo; 18 | internal SVIDAttribute SVIDInfo; 19 | 20 | internal SVIDMapInfo(PropertyInfo pi, SVIDAttribute svAttr) 21 | { 22 | this.PropertyInfo = pi; 23 | this.SVIDInfo = svAttr; 24 | } 25 | } 26 | 27 | #endregion 28 | 29 | public SVAttributeMapper(EquipmentModel model) 30 | { 31 | m_SVAttributeDic = new Dictionary(); 32 | m_Model = model; 33 | m_Model.SetSVIDMapper(this); 34 | Map(m_Model); 35 | } 36 | 37 | private void Map(EquipmentModel model) 38 | { 39 | m_SVAttributeDic.Clear(); 40 | 41 | Type eqType = model.GetType(); 42 | Type svAttributeType = typeof(SVIDAttribute); 43 | SVIDAttribute svAttribute; 44 | 45 | PropertyInfo[] props = eqType.GetProperties(); 46 | SVIDMapInfo mi = null; 47 | 48 | foreach (PropertyInfo pi in props) 49 | { 50 | if (pi.CanWrite && pi.IsDefined(svAttributeType, true)) 51 | { 52 | object[] attrs = pi.GetCustomAttributes(svAttributeType, true); 53 | svAttribute = (SVIDAttribute)attrs[0]; 54 | if (m_SVAttributeDic.ContainsKey(svAttribute.ID)) 55 | { 56 | //throw error 57 | throw new Exception(string.Format("Duplicated SVID {0} PropertyName := {1}", svAttribute.ID, pi.Name)); 58 | } 59 | 60 | mi = new SVIDMapInfo(pi, svAttribute); 61 | 62 | m_SVAttributeDic.Add(svAttribute.ID, mi); 63 | 64 | } 65 | } 66 | } 67 | 68 | public void ObtainSvValueFromS6F11(SecsMessageBase s6f11) 69 | { 70 | SecsItemList secsItem_L3 = (SecsItemList)s6f11.Items[0]; 71 | SecsItem secsItem_DataID = secsItem_L3.Value[0]; 72 | SecsItem secsItem_CEID = secsItem_L3.Value[1]; 73 | SecsItemList secsItem_La = (SecsItemList)secsItem_L3.Value[2]; 74 | 75 | SecsItem secsItem_RPTID = null; 76 | SecsItemList secsItem_Lb = null; 77 | 78 | foreach (SecsItemList secsItem_L2 in secsItem_La.Value) 79 | { 80 | secsItem_RPTID = secsItem_L2.Value[0]; 81 | secsItem_Lb = (SecsItemList)secsItem_L2.Value[1]; 82 | 83 | for (int index = 0; index < secsItem_Lb.Value.Count; index++) 84 | { 85 | object dfSvid = InternalGetDefinedSVID(secsItem_RPTID, index); 86 | if (m_SVAttributeDic.ContainsKey(dfSvid)) 87 | { 88 | SVIDMapInfo mi = m_SVAttributeDic[dfSvid]; 89 | SetStatusVariable(mi, secsItem_Lb.Value[index]); 90 | } 91 | else 92 | { 93 | //throw error 94 | } 95 | } 96 | } 97 | } 98 | 99 | private void SetStatusVariable(SVIDMapInfo mi, SecsItem secsItem_SV) 100 | { 101 | //2.) Get value from secs item 102 | object val = null; 103 | 104 | SVIDAttribute svAttr = mi.SVIDInfo; 105 | 106 | if (secsItem_SV is SecsItemU1) 107 | { 108 | if (svAttr.Size == 1) 109 | { 110 | val = ((SecsItemU1)secsItem_SV).Value[0]; 111 | } 112 | else 113 | { 114 | val = ((SecsItemU1)secsItem_SV).Value; 115 | } 116 | } 117 | else if (secsItem_SV is SecsItemU2) 118 | { 119 | if (svAttr.Size == 1) 120 | { 121 | val = ((SecsItemU2)secsItem_SV).Value[0]; 122 | } 123 | else 124 | { 125 | val = ((SecsItemU2)secsItem_SV).Value; 126 | } 127 | } 128 | else if (secsItem_SV is SecsItemU4) 129 | { 130 | if (svAttr.Size == 1) 131 | { 132 | val = ((SecsItemU4)secsItem_SV).Value[0]; 133 | } 134 | else 135 | { 136 | val = ((SecsItemU4)secsItem_SV).Value; 137 | } 138 | } 139 | else if (secsItem_SV is SecsItemU8) 140 | { 141 | if (svAttr.Size == 1) 142 | { 143 | val = ((SecsItemU8)secsItem_SV).Value[0]; 144 | } 145 | else 146 | { 147 | val = ((SecsItemU8)secsItem_SV).Value; 148 | } 149 | } 150 | else if (secsItem_SV is SecsItemI1) 151 | { 152 | if (svAttr.Size == 1) 153 | { 154 | val = ((SecsItemI1)secsItem_SV).Value[0]; 155 | } 156 | else 157 | { 158 | val = ((SecsItemI1)secsItem_SV).Value; 159 | } 160 | } 161 | else if (secsItem_SV is SecsItemI2) 162 | { 163 | if (svAttr.Size == 1) 164 | { 165 | val = ((SecsItemI2)secsItem_SV).Value[0]; 166 | } 167 | else 168 | { 169 | val = ((SecsItemI2)secsItem_SV).Value; 170 | } 171 | } 172 | else if (secsItem_SV is SecsItemI4) 173 | { 174 | if (svAttr.Size == 1) 175 | { 176 | val = ((SecsItemI4)secsItem_SV).Value[0]; 177 | } 178 | else 179 | { 180 | val = ((SecsItemI4)secsItem_SV).Value; 181 | } 182 | } 183 | else if (secsItem_SV is SecsItemI8) 184 | { 185 | if (svAttr.Size == 1) 186 | { 187 | val = ((SecsItemI8)secsItem_SV).Value[0]; 188 | } 189 | else 190 | { 191 | val = ((SecsItemI8)secsItem_SV).Value; 192 | } 193 | } 194 | else if (secsItem_SV is SecsItemBinary) 195 | { 196 | if (svAttr.Size == 1) 197 | { 198 | val = ((SecsItemBinary)secsItem_SV).Value[0]; 199 | } 200 | else 201 | { 202 | val = ((SecsItemBinary)secsItem_SV).Value; 203 | } 204 | } 205 | else if (secsItem_SV is SecsItemAscii) 206 | { 207 | val = ((SecsItemAscii)secsItem_SV).Value; 208 | } 209 | else if (secsItem_SV is SecsItemBoolean) 210 | { 211 | if (svAttr.Size == 1) 212 | { 213 | val = ((SecsItemBoolean)secsItem_SV).Value[0]; 214 | } 215 | else 216 | { 217 | val = ((SecsItemBoolean)secsItem_SV).Value; 218 | } 219 | } 220 | else 221 | { 222 | throw new Exception("Not support type " + secsItem_SV.GetType().Name); 223 | } 224 | 225 | PropertyInfo pi = mi.PropertyInfo; 226 | pi.SetValue(m_Model, val, null); 227 | } 228 | 229 | internal abstract object InternalGetDefinedSVID(SecsItem secsItem_RptID, int index); 230 | 231 | } 232 | 233 | public abstract class SVAttributeMapper 234 | : SVAttributeMapper 235 | { 236 | 237 | public SVAttributeMapper(EquipmentModel model) 238 | : base(model) 239 | { 240 | } 241 | 242 | internal override object InternalGetDefinedSVID(SecsItem secsItem_RptID, int index) 243 | { 244 | return GetDefinedSVID(secsItem_RptID, index); 245 | } 246 | 247 | protected abstract SVID GetDefinedSVID(SecsItem secsItem_RptID, int index); 248 | } 249 | 250 | } 251 | -------------------------------------------------------------------------------- /SecsGem/SecsDataItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsDataItem 9 | { 10 | private string m_Name; 11 | private FormatCode m_Format; 12 | private FormatCode[] m_PosibleFormats; 13 | 14 | private int m_ItemLength; 15 | 16 | public string Name 17 | { 18 | get { 19 | return m_Name; 20 | } 21 | } 22 | 23 | public FormatCode Format 24 | { 25 | get { 26 | return m_Format; 27 | } 28 | set 29 | { 30 | bool matched = false; 31 | foreach (FormatCode f in m_PosibleFormats) 32 | { 33 | if (f == value) 34 | { 35 | matched = true; 36 | } 37 | } 38 | if (!matched) 39 | { 40 | throw new Exception("Not posible format"); 41 | } 42 | m_Format = value; 43 | } 44 | } 45 | 46 | public SecsDataItem(string name, FormatCode fCode, int itemLength, params FormatCode[] possibleFormats) 47 | { 48 | m_Name = name; 49 | m_Format = fCode; 50 | m_ItemLength = itemLength; 51 | m_PosibleFormats = possibleFormats; 52 | } 53 | 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /SecsGem/SecsHost.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading; 5 | using System.IO; 6 | 7 | namespace XtraLibrary.SecsGem 8 | { 9 | public abstract class SecsHost 10 | { 11 | 12 | #region "Extended properties" 13 | 14 | //************************************ 15 | //Added By Tanapat S. since 2017-09-21 16 | //************************************ 17 | /// 18 | /// For keep Machine name ... requested by Mr.Prasarn 19 | /// 20 | public string Name { get; set; } 21 | //************************************ 22 | 23 | #endregion 24 | 25 | #region "Variables" 26 | 27 | private object m_Locker; 28 | 29 | private SecsItemManager m_ItemManager; 30 | private Dictionary m_SecsTransaction; 31 | private Dictionary c_CustomSecondaryMessageCallback; 32 | 33 | private ushort m_DeviceId; 34 | private uint m_TransactionIdSeed; 35 | protected SynchronizationContext m_SyncContext; 36 | 37 | private bool m_SecsLogEnabled; 38 | protected string m_LogDirectory; 39 | 40 | protected SecsMessageParserBase m_Parser; 41 | 42 | #endregion 43 | 44 | #region "Events" 45 | 46 | public event TraceLogEventHandler TracedSmlLog; 47 | public event SecsErrorNotificationEventHandler ErrorNotification; 48 | public event PrimarySecsMessageEventHandler ReceivedPrimaryMessage; 49 | public event SecondarySecsMessageEventHandler ReceivedSecondaryMessage; 50 | public event ConversionErrorEventHandler ConversionErrored; 51 | 52 | #endregion 53 | 54 | #region "Properties" 55 | 56 | public ushort DeviceId 57 | { 58 | get { 59 | return m_DeviceId; 60 | } 61 | set { 62 | m_DeviceId = value; 63 | } 64 | } 65 | 66 | public bool SecsLogEnabled 67 | { 68 | get { 69 | return m_SecsLogEnabled; 70 | } 71 | set 72 | { 73 | m_SecsLogEnabled = value; 74 | } 75 | } 76 | 77 | public string LogDirectory 78 | { 79 | get { 80 | return m_LogDirectory; 81 | } 82 | set 83 | { 84 | m_LogDirectory = value; 85 | } 86 | } 87 | 88 | public SecsMessageParserBase MessageParser 89 | { 90 | get { 91 | return m_Parser; 92 | } 93 | } 94 | 95 | #endregion 96 | 97 | protected SecsHost(SecsMessageParserBase parser) 98 | { 99 | m_Locker = new object(); 100 | m_Parser = parser; 101 | m_ItemManager = new SecsItemManager(); 102 | m_DeviceId = 0; 103 | m_SecsTransaction = new Dictionary(); 104 | c_CustomSecondaryMessageCallback = new Dictionary(); 105 | m_TransactionIdSeed = 0; 106 | 107 | m_SyncContext = SynchronizationContext.Current; 108 | if (m_SyncContext == null) 109 | { 110 | m_SyncContext = new SynchronizationContext(); 111 | } 112 | 113 | m_SecsLogEnabled = true; 114 | System.IO.FileInfo fi = new FileInfo(System.Reflection.Assembly.GetExecutingAssembly().Location); 115 | m_LogDirectory = fi.DirectoryName; 116 | } 117 | 118 | #region "Logging" 119 | 120 | private void TraceSmlLog(SecsMessageBase msg, DirectionType direction) 121 | { 122 | DateTime time = DateTime.Now; 123 | //conver to SML 124 | string strSml = SmlBuilder.ToSmlString(msg); 125 | //create log message 126 | string logMsg = String.Format("{0:yyyy/MM/dd HH:mm:ss.fff} [{1}] " + 127 | Environment.NewLine + "{2}", time, direction, strSml); 128 | 129 | //keep to text file 130 | if (m_SecsLogEnabled) 131 | { 132 | WritSmlLog(logMsg); 133 | } 134 | //raise event 135 | PostEvent_TracedSmlLog(new TraceLogEventArgs(time, strSml, direction, logMsg)); 136 | } 137 | 138 | private void WritSmlLog(string logMsg) 139 | { 140 | 141 | lock (m_Locker) 142 | { 143 | string fileName = Path.Combine(m_LogDirectory, "SECS_" + DateTime.Now.ToString("yyyyMMdd") + ".log"); 144 | using (StreamWriter writer = new StreamWriter(fileName, true)) 145 | { 146 | 147 | writer.WriteLine(logMsg); 148 | } 149 | } 150 | } 151 | 152 | #endregion 153 | 154 | #region "Post Events" 155 | 156 | private void PostEvent_ErrorNotification(SecsErrorNotificationEventArgs e) 157 | { 158 | if (ErrorNotification != null) 159 | { 160 | m_SyncContext.Post((object state) => 161 | { 162 | ErrorNotification(this, (SecsErrorNotificationEventArgs)state); 163 | }, e); 164 | } 165 | } 166 | 167 | private void PostEvent_TracedSmlLog(TraceLogEventArgs e) 168 | { 169 | if (TracedSmlLog != null) 170 | { 171 | m_SyncContext.Post((object state) => 172 | { 173 | 174 | TracedSmlLog(this, (TraceLogEventArgs)state); 175 | 176 | }, e); 177 | } 178 | } 179 | 180 | private void PostEvent_ReceivedPrimaryMessage(PrimarySecsMessageEventArgs e) 181 | { 182 | if (ReceivedPrimaryMessage != null) 183 | { 184 | m_SyncContext.Post((object state) => 185 | { 186 | ReceivedPrimaryMessage(this, e); 187 | }, null); 188 | } 189 | } 190 | 191 | private void PostEvent_ReceivedSecondaryMessage(SecondarySecsMessageEventArgs e) 192 | { 193 | if (ReceivedSecondaryMessage != null) 194 | { 195 | m_SyncContext.Post((object state) => 196 | { 197 | ReceivedSecondaryMessage(this, e); 198 | }, null); 199 | } 200 | } 201 | 202 | private void PoseEvent_ConversionErrored(ConversionErrorEventArgs e) { 203 | if (ConversionErrored != null) 204 | { 205 | m_SyncContext.Post((object state) => 206 | { 207 | ConversionErrored(this, e); 208 | }, null); 209 | } 210 | } 211 | 212 | #endregion 213 | 214 | #region "Abstract methods" 215 | 216 | public abstract void Connect(); 217 | public abstract void Disconnect(); 218 | 219 | //Sending ... 220 | protected virtual void OnSending(SecsMessageBase msg, bool isPrimary) { } 221 | //protected virtual void OnSent(SecsMessageBase msg) { } 222 | protected abstract void ProtectedSend(byte[] data); 223 | 224 | //Receiving 225 | protected virtual void OnReceiving(SecsMessageBase msg, bool isSecondary) { } 226 | protected virtual void OnReceived(SecsMessageBase msg) { } 227 | 228 | #endregion 229 | 230 | #region "SECS MESSAGE BUILD" 231 | 232 | #region "Request message" 233 | 234 | 235 | #endregion 236 | 237 | #region "Reply message" 238 | 239 | //Message Fault — A Message Fault occurs when the equipment receives a message 240 | //which it cannot process because of a fault that arises from the content, 241 | //context, or length of the message 242 | public void Reply_AbortMessage(SecsMessageBase msg) 243 | { 244 | SecsMessage sm = new SecsMessage(9, 0, false); 245 | sm.TransactionId = msg.TransactionId; 246 | Send(sm); 247 | } 248 | 249 | #endregion 250 | 251 | #endregion 252 | 253 | #region "Public methods" 254 | 255 | /// 256 | /// S1F15R Request OFF-LINE 257 | /// 258 | public void Request_OFFLINE() 259 | { 260 | SecsMessage sm = new SecsMessage(1, 15, true); 261 | Send(sm); 262 | } 263 | 264 | /// 265 | /// S1F17R Request ON-LINE 266 | /// 267 | public void Request_ONLINE() 268 | { 269 | SecsMessage sm = new SecsMessage(1, 17, true); 270 | Send(sm); 271 | } 272 | 273 | /// 274 | /// S1F13R Establish Communications Request 275 | /// 276 | public void EstablishCommunicationsRequest() 277 | { 278 | SecsMessage sm = new SecsMessage(1, 13, true); 279 | sm.Items.Add(new SecsItemList("L0")); 280 | Send(sm); 281 | } 282 | 283 | public void Send(SecsMessageBase msg) 284 | { 285 | Send(msg, null); 286 | } 287 | 288 | public void Send(SecsMessageBase msg, SecondarySecsMessageEventHandler callback) 289 | { 290 | msg.DeviceId = m_DeviceId; 291 | 292 | bool isPrimary = msg.NeedReply && ((msg.Function & 0x01) == 0x01); 293 | 294 | if (isPrimary) 295 | { 296 | //get new transaction id 297 | msg.TransactionId = GetNextTransactionId(); 298 | 299 | //register T3 300 | lock (m_Locker) 301 | { 302 | if (m_SecsTransaction.ContainsKey(msg.TransactionId)) 303 | { 304 | m_SecsTransaction.Remove(msg.TransactionId); 305 | } 306 | m_SecsTransaction.Add(msg.TransactionId, msg); 307 | } 308 | 309 | if (callback != null) 310 | { 311 | if (c_CustomSecondaryMessageCallback.ContainsKey(msg.TransactionId)) 312 | { 313 | c_CustomSecondaryMessageCallback.Remove(msg.TransactionId); 314 | } 315 | c_CustomSecondaryMessageCallback.Add(msg.TransactionId, callback); 316 | } 317 | } 318 | 319 | 320 | //TraceSmlLog(msg, DirectionType.Sent); 321 | OnSending(msg, isPrimary); 322 | byte[] data = m_Parser.GetBytes(msg); 323 | ProtectedSend(data); 324 | //OnSent(msg); 325 | TraceSmlLog(msg, DirectionType.Sent); 326 | } 327 | 328 | public void Reply(SecsMessageBase primary, SecsMessageBase secondaryMessage) 329 | { 330 | secondaryMessage.TransactionId = primary.TransactionId; 331 | Send(secondaryMessage); 332 | } 333 | 334 | //public void DefinedReport() 335 | //{ 336 | 337 | //} 338 | 339 | //public void DeleteAllReport() 340 | //{ 341 | 342 | //} 343 | 344 | //public void LinkReport() 345 | //{ 346 | 347 | //} 348 | 349 | //public void EnabledReport() 350 | //{ 351 | 352 | //} 353 | 354 | #endregion 355 | 356 | protected uint GetNextTransactionId() 357 | { 358 | uint ret = 0; 359 | 360 | lock (m_Locker) 361 | { 362 | if (m_TransactionIdSeed == uint.MaxValue) 363 | { 364 | m_TransactionIdSeed = 1; 365 | } 366 | else 367 | { 368 | m_TransactionIdSeed += 1; 369 | } 370 | 371 | ret = m_TransactionIdSeed; 372 | } 373 | 374 | return ret; 375 | } 376 | 377 | /// 378 | /// This function is called from inherited class 379 | /// 380 | /// SecsMessage in byte[] 381 | protected void ProcessSecsMessageBytes(byte[] data) 382 | { 383 | SecsMessageBase msg = null; 384 | try 385 | { 386 | msg = m_Parser.ToSecsMessage(data); 387 | } 388 | catch (Exception ex) 389 | { 390 | //fire out event conversion error 391 | PoseEvent_ConversionErrored(new ConversionErrorEventArgs(ex, data)); 392 | return; 393 | } 394 | 395 | TraceSmlLog(msg, DirectionType.Recv); 396 | 397 | bool isSecondary = (msg.Function & 0x01) == 0x00; 398 | 399 | OnReceiving(msg, isSecondary); 400 | //should put some flag for example :Cancel or abort 401 | OnReceived(msg); 402 | 403 | if (isSecondary) 404 | { 405 | SecsMessageBase priMsg = null; 406 | 407 | lock (m_Locker) 408 | { 409 | if (m_SecsTransaction.ContainsKey(msg.TransactionId)) 410 | { 411 | //get primary message 412 | priMsg = m_SecsTransaction[msg.TransactionId]; 413 | //unregister transaction 414 | m_SecsTransaction.Remove(msg.TransactionId); 415 | } 416 | } 417 | 418 | if (priMsg != null) 419 | { 420 | if (msg.Function == 0) 421 | { 422 | //primary transaction was abort 423 | AbortPrimaryTransaction(msg); 424 | } 425 | else 426 | { 427 | //custom callback checking 428 | if (c_CustomSecondaryMessageCallback.ContainsKey(priMsg.TransactionId)) 429 | { 430 | //get callback from dictionary 431 | SecondarySecsMessageEventHandler callback = c_CustomSecondaryMessageCallback[priMsg.TransactionId]; 432 | //remove callnack from dictionary 433 | c_CustomSecondaryMessageCallback.Remove(priMsg.TransactionId); 434 | //execute callback 435 | callback(this, new SecondarySecsMessageEventArgs(priMsg, msg)); 436 | } 437 | else 438 | { 439 | //should post as asynchronouse 440 | PostEvent_ReceivedSecondaryMessage(new SecondarySecsMessageEventArgs(priMsg, msg)); 441 | } 442 | } 443 | } 444 | else 445 | { 446 | AbortUnknowTransaction(msg); 447 | } 448 | 449 | } 450 | else 451 | { 452 | //should post as asynchronouse 453 | PostEvent_ReceivedPrimaryMessage(new PrimarySecsMessageEventArgs(msg)); 454 | } 455 | 456 | } 457 | 458 | private void AbortPrimaryTransaction(SecsMessageBase priMsg) 459 | { 460 | PostEvent_ErrorNotification(new SecsErrorNotificationEventArgs("Transaction Aborted", priMsg)); 461 | } 462 | 463 | private void AbortUnknowTransaction(SecsMessageBase msg) 464 | { 465 | PostEvent_ErrorNotification(new SecsErrorNotificationEventArgs("Unknow Transaction", msg)); 466 | } 467 | 468 | protected void TransactionTimeout(uint transactionId) 469 | { 470 | SecsMessageBase msg = null; 471 | lock (m_Locker) 472 | { 473 | if (m_SecsTransaction.ContainsKey(transactionId)) 474 | { 475 | msg = m_SecsTransaction[transactionId]; 476 | m_SecsTransaction.Remove(transactionId); 477 | } 478 | else 479 | { 480 | //unknow transaction 481 | return; 482 | } 483 | } 484 | 485 | if (msg != null) 486 | { 487 | PostEvent_ErrorNotification(new SecsErrorNotificationEventArgs("Transaction Timeout", msg)); 488 | } 489 | else 490 | { 491 | PostEvent_ErrorNotification(new SecsErrorNotificationEventArgs("Transaction Timeout", transactionId)); 492 | } 493 | } 494 | 495 | } 496 | } 497 | -------------------------------------------------------------------------------- /SecsGem/SecsHostFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsHostFactory 9 | { 10 | public SecsHostFactory() { 11 | 12 | } 13 | 14 | public SecsHost Create(EquipmentModel eqModel) 15 | { 16 | GemOption opt = eqModel.Connection; 17 | 18 | SecsHost host = null; 19 | 20 | if (opt.Protocol == GemProtocol.HSMS) 21 | { 22 | host = new HsmsHost(opt.HsmsParameters); 23 | } 24 | else if (opt.Protocol == GemProtocol.SECS_I) 25 | { 26 | host = new SecsIHost(opt.SecsIParameters); 27 | } 28 | 29 | host.DeviceId = opt.DeviceId; 30 | 31 | return host; 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /SecsGem/SecsIHost.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | using System.IO.Ports; 6 | using System.Collections; 7 | 8 | namespace XtraLibrary.SecsGem 9 | { 10 | public class SecsIHost 11 | :SecsHost 12 | { 13 | 14 | public event SecsIConnectionChangedEventHandler ConnectionChanged; 15 | 16 | public SecsIHost() 17 | :this(new SecsIParameters(), new SecsIMessageParser()) 18 | { 19 | 20 | } 21 | 22 | public SecsIHost(SecsIParameters parameters) 23 | :this(parameters, new SecsIMessageParser()) 24 | { 25 | } 26 | 27 | public SecsIHost(SecsIParameters parameters, SecsIMessageParser parser) 28 | : base(parser) 29 | { 30 | m_QueueSendingBlock = new Queue(); 31 | 32 | m_RecvBuff = new byte[1024]; //actually use only 258 bytes 33 | 34 | m_Port = new SerialPort(); 35 | m_Port.DataReceived += new SerialDataReceivedEventHandler(m_Port_DataReceived); 36 | 37 | m_ENQ = new byte[] { 5 }; 38 | m_EOT = new byte[] { 4 }; 39 | m_ACK = new byte[] { 6 }; 40 | m_NAK = new byte[] { 7 }; 41 | 42 | m_T1_Timer = new System.Timers.Timer(); 43 | m_T1_Timer.Elapsed += new System.Timers.ElapsedEventHandler(T1_Elapsed); 44 | m_T2_Timer = new System.Timers.Timer(); 45 | m_T2_Timer.Elapsed += new System.Timers.ElapsedEventHandler(T2_Elapsed); 46 | 47 | m_Parameters = parameters; 48 | 49 | m_State = CommuState.Idle; 50 | 51 | m_MultiBlockList = new List(); 52 | 53 | m_T3Hash = new Hashtable(); 54 | 55 | m_Locker = new object(); 56 | } 57 | 58 | #region "Properties" 59 | 60 | public new SecsIMessageParser MessageParser 61 | { 62 | get 63 | { 64 | return (SecsIMessageParser)m_Parser; 65 | } 66 | 67 | set 68 | { 69 | m_Parser = value; 70 | } 71 | } 72 | 73 | #endregion 74 | 75 | #region "Post Events" 76 | 77 | public void PoseEvent_ConnectionChanged() 78 | { 79 | if (ConnectionChanged != null) 80 | { 81 | m_SyncContext.Post((object state) => { 82 | ConnectionChanged(this, new SecsIConnectionChangedEventArgs(m_Port.IsOpen)); 83 | }, null); 84 | } 85 | } 86 | 87 | #endregion 88 | 89 | #region "Abstract Methods" 90 | 91 | public override void Connect() 92 | { 93 | System.Diagnostics.Debug.Print("Connect"); 94 | m_Port.PortName = m_Parameters.PortName; 95 | m_Port.BaudRate = m_Parameters.BaudRate; 96 | m_Port.Open(); 97 | System.Diagnostics.Debug.Print("PortIsOpen =" + m_Port.IsOpen); 98 | PoseEvent_ConnectionChanged(); 99 | } 100 | 101 | public override void Disconnect() 102 | { 103 | System.Diagnostics.Debug.Print("Disconnect"); 104 | m_Port.Close(); 105 | PoseEvent_ConnectionChanged(); 106 | } 107 | 108 | protected override void ProtectedSend(byte[] data) 109 | { 110 | SendBytes(data); 111 | } 112 | protected override void OnReceiving(SecsMessageBase msg, bool isSecondary) 113 | { 114 | if (isSecondary) 115 | { 116 | Stop_T3_Timer(msg.TransactionId); 117 | } 118 | } 119 | 120 | protected override void OnSending(SecsMessageBase msg, bool isPrimary) 121 | { 122 | if (isPrimary) 123 | { 124 | Start_T3_Timer(msg.TransactionId); 125 | } 126 | } 127 | 128 | #endregion 129 | 130 | #region "SECS-I driver" 131 | 132 | #region "Properties" 133 | 134 | //public SerialPort Port 135 | //{ 136 | // get 137 | // { 138 | // return m_Port; 139 | // } 140 | //} 141 | 142 | #endregion 143 | 144 | #region "Variables" 145 | 146 | private object m_Locker; 147 | 148 | private CommuState m_State; 149 | private SerialPort m_Port; 150 | 151 | private int m_RecvBuffIndex; 152 | private byte[] m_RecvBuff; 153 | 154 | private byte[] m_ENQ; 155 | private byte[] m_EOT; 156 | private byte[] m_ACK; 157 | private byte[] m_NAK; 158 | 159 | //SECS-I timeout 160 | private System.Timers.Timer m_T1_Timer = new System.Timers.Timer(); 161 | private System.Timers.Timer m_T2_Timer = new System.Timers.Timer(); 162 | 163 | private SecsIParameters m_Parameters; 164 | 165 | List m_MultiBlockList; 166 | 167 | private Queue m_QueueSendingBlock; 168 | 169 | private Hashtable m_T3Hash; 170 | 171 | private int m_T2_RetryCount; 172 | 173 | #endregion 174 | 175 | private enum HandshakeCodes :byte 176 | { 177 | ENQ = 5, 178 | EOT = 4, 179 | ACK = 6, 180 | NAK = 21 181 | } 182 | 183 | private enum CommuState 184 | { 185 | Idle = 0, 186 | Send_Request = 1, 187 | Sending = 2, 188 | Receiving = 3 189 | } 190 | 191 | #region "Timers" 192 | 193 | private void Start_T1_Timer() 194 | { 195 | m_T1_Timer.Interval = m_Parameters.T1_Interval * 1000; 196 | m_T1_Timer.Start(); 197 | } 198 | 199 | private void Stop_T1_Timer() 200 | { 201 | m_T1_Timer.Stop(); 202 | } 203 | 204 | private void Start_T2_Timer() 205 | { 206 | m_T2_Timer.Interval = m_Parameters.T2_Interval * 1000; 207 | m_T2_Timer.Start(); 208 | } 209 | 210 | private void Stop_T2_Timer() 211 | { 212 | m_T2_RetryCount = 0; 213 | m_T2_Timer.Stop(); 214 | } 215 | 216 | private void Start_T3_Timer(uint tid) 217 | { 218 | System.Diagnostics.Debug.Print("Start_T3_Timer [TID:{0}]", tid); 219 | 220 | T3Timer timer_t3 = new T3Timer(tid); 221 | timer_t3.Interval = m_Parameters.T3_Interval * 1000; 222 | timer_t3.Elapsed += new System.Timers.ElapsedEventHandler(T3_Elapsed); 223 | timer_t3.Start(); 224 | m_T3Hash.Add(tid, timer_t3); 225 | } 226 | 227 | private void Stop_T3_Timer(uint tid) 228 | { 229 | System.Diagnostics.Debug.Print("Stop_T3_Timer [TID:{0}]", tid); 230 | if (m_T3Hash.ContainsKey(tid)) 231 | { 232 | T3Timer timer_t3 = (T3Timer)m_T3Hash[tid]; 233 | timer_t3.Stop(); 234 | m_T3Hash.Remove(tid); 235 | } 236 | } 237 | 238 | private void T3_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 239 | { 240 | T3Timer timer_t3 = (T3Timer)sender; 241 | timer_t3.Stop(); 242 | m_T3Hash.Remove(timer_t3.TransactionId); 243 | base.TransactionTimeout(timer_t3.TransactionId); 244 | System.Diagnostics.Debug.Print("T3_Elapsed [TID:{0}]", timer_t3.TransactionId); 245 | timer_t3.Dispose(); 246 | } 247 | 248 | /// 249 | /// T2 TIMEOUT 250 | /// 1. NO EOT AFTER ENQ 251 | /// 2. NO ACK/NAK AFTER MESSAGE 252 | /// 3. NO MESSAGE AFTER EOT 253 | /// 254 | /// 255 | /// 256 | private void T2_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 257 | { 258 | SendHandshakeCode(HandshakeCodes.ENQ); 259 | m_T2_RetryCount += 1; 260 | if (m_T2_RetryCount > m_Parameters.RTY) 261 | { 262 | Stop_T2_Timer(); 263 | } 264 | } 265 | 266 | private void T1_Elapsed(object sender, System.Timers.ElapsedEventArgs e) 267 | { 268 | m_T1_Timer.Stop(); 269 | m_State = CommuState.Idle; 270 | SendHandshakeCode(HandshakeCodes.NAK); 271 | } 272 | 273 | #endregion 274 | 275 | #region "Receiving" 276 | 277 | private void m_Port_DataReceived(object sender, SerialDataReceivedEventArgs e) 278 | { 279 | lock (m_Locker) 280 | { 281 | byte[] buff = new byte[m_Port.BytesToRead]; 282 | int length = m_Port.Read(buff, 0, buff.Length); 283 | 284 | System.Diagnostics.Debug.Print("DataReceived {0} bytes , State {1}", length, m_State); 285 | System.Diagnostics.Debug.Print("Hex : " + GetHexString(buff)); 286 | 287 | if (length == 0) 288 | { 289 | return; 290 | } 291 | 292 | switch(m_State) 293 | { 294 | case CommuState.Idle : 295 | if (length == 1) 296 | { 297 | System.Diagnostics.Debug.Print("RecvControlChar := "+ (HandshakeCodes)buff[0]); 298 | if ((HandshakeCodes)buff[0] == HandshakeCodes.ENQ) 299 | { 300 | m_State = CommuState.Receiving; 301 | SendHandshakeCode(HandshakeCodes.EOT); 302 | //3. NO MESSAGE AFTER EOT 303 | Start_T1_Timer(); 304 | } 305 | } 306 | break; 307 | case CommuState.Receiving: 308 | Stop_T2_Timer(); 309 | OnDataArrival(buff, length); 310 | 311 | break; 312 | case CommuState.Send_Request : 313 | System.Diagnostics.Debug.Print("RecvControlChar := " + (HandshakeCodes)buff[0]); 314 | if ((HandshakeCodes)buff[0] == HandshakeCodes.EOT) 315 | { 316 | Stop_T2_Timer(); 317 | m_State = CommuState.Sending; 318 | StartSend(); 319 | } 320 | break; 321 | case CommuState.Sending: 322 | System.Diagnostics.Debug.Print("RecvControlChar := " + (HandshakeCodes)buff[0]); 323 | if ((HandshakeCodes)buff[0] == HandshakeCodes.ACK) 324 | { 325 | Stop_T2_Timer(); 326 | m_State = CommuState.Idle; 327 | } 328 | else if ((HandshakeCodes)buff[0] == HandshakeCodes.NAK) 329 | { 330 | Stop_T2_Timer(); 331 | m_State = CommuState.Idle; //message failed 332 | } 333 | break; 334 | } 335 | } 336 | 337 | if (m_State == CommuState.Idle && m_QueueSendingBlock.Count > 0) 338 | { 339 | RequestToSend(); 340 | } 341 | } 342 | 343 | private void OnDataArrival(byte[] buffer, int length) 344 | { 345 | Array.Copy(buffer, 0, m_RecvBuff, m_RecvBuffIndex, length); 346 | m_RecvBuffIndex += length; 347 | 348 | System.Diagnostics.Debug.Print("RecvBuffIndex := " + m_RecvBuffIndex.ToString()); 349 | 350 | if (m_RecvBuffIndex > 0) 351 | { 352 | //LTH[0] << length of data 1 + CHECKSUM 2 353 | byte lth = m_RecvBuff[0]; 354 | 355 | Stop_T1_Timer(); 356 | 357 | //wait until end of block 358 | if (lth + 3 == m_RecvBuffIndex) 359 | { 360 | ushort checksumCal = 0; 361 | for (int i = 1; i < m_RecvBuffIndex - 2; i++) 362 | { 363 | checksumCal += m_RecvBuff[i]; 364 | } 365 | 366 | ushort checksumRecv = BitConverter.ToUInt16( 367 | new byte[] { 368 | m_RecvBuff[m_RecvBuffIndex - 1], 369 | m_RecvBuff[m_RecvBuffIndex - 2] 370 | }, 0); 371 | 372 | if (checksumCal == checksumRecv) 373 | { 374 | //change State to idle 375 | m_State = CommuState.Idle; 376 | //if CHECK SUM is correct 377 | SendHandshakeCode(HandshakeCodes.ACK); 378 | 379 | byte[] header = new byte[10]; 380 | 381 | Array.Copy(m_RecvBuff, 1, header, 0, header.Length); 382 | 383 | System.Diagnostics.Debug.Print("HEAD {0} bytes ", header.Length); 384 | 385 | byte[] transactionIdBytes = new byte[4]; 386 | Array.Copy(header, 6, transactionIdBytes, 0, 4); 387 | Array.Reverse(transactionIdBytes); 388 | 389 | //transaction Id alway same in Multi-Block message 390 | uint tid = BitConverter.ToUInt32(transactionIdBytes, 0); 391 | System.Diagnostics.Debug.Print("Transaction ID {0} bytes ", tid); 392 | 393 | int bodyLength = lth - 10; 394 | 395 | if (bodyLength > 0) 396 | { 397 | byte[] body = new byte[bodyLength]; 398 | Array.Copy(m_RecvBuff, 11, body, 0, bodyLength); 399 | 400 | System.Diagnostics.Debug.Print("BODY {0} bytes ", body.Length); 401 | 402 | m_MultiBlockList.Add(body); 403 | } 404 | 405 | if ((header[4] & 0x80) == 0x80) //last block 406 | { 407 | //build up all message 408 | int totalBytes = 10; //header 409 | 410 | foreach (byte[] bytes in m_MultiBlockList) 411 | { 412 | totalBytes += bytes.Length; 413 | } 414 | 415 | byte[] data = new byte[totalBytes]; 416 | int index = 0; 417 | 418 | Array.Copy(header, 0, data, 0, header.Length); 419 | index += header.Length; 420 | 421 | foreach (byte[] bytes in m_MultiBlockList) 422 | { 423 | Array.Copy(bytes, 0, data, index, bytes.Length); 424 | index += bytes.Length; 425 | } 426 | 427 | m_MultiBlockList.Clear(); 428 | 429 | ProcessSecsMessageBytes(data); 430 | } 431 | } 432 | else 433 | { 434 | //send NAK for check sum error 435 | SendHandshakeCode(HandshakeCodes.NAK); 436 | } 437 | 438 | //clear buffer 439 | Array.Clear(m_RecvBuff, 0, m_RecvBuffIndex); 440 | m_RecvBuffIndex = 0; 441 | } 442 | else 443 | { 444 | Start_T1_Timer(); 445 | } 446 | } //if (m_RecvBuffIndex > 0) 447 | } 448 | 449 | #endregion 450 | 451 | private string GetHexString(byte[] data) 452 | { 453 | StringBuilder sb = new StringBuilder(); 454 | 455 | foreach (byte b in data) 456 | { 457 | if (sb.Length == 0) 458 | { 459 | sb.Append(b.ToString("X2")); 460 | } 461 | else 462 | { 463 | sb.Append(" " + b.ToString("X2")); 464 | } 465 | } 466 | 467 | return sb.ToString(); 468 | } 469 | 470 | #region "Sending" 471 | 472 | private void StartSend() 473 | { 474 | lock (m_Locker) 475 | { 476 | byte[] data = m_QueueSendingBlock.Dequeue(); 477 | 478 | System.Diagnostics.Debug.Print("StartSend {0}", data.Length); 479 | System.Diagnostics.Debug.Print("Hex :=" + GetHexString(data)); 480 | 481 | m_Port.Write(data, 0, 1); 482 | m_Port.Write(data, 1, data.Length - 3); 483 | m_Port.Write(data, data.Length - 2, 2); 484 | 485 | //2. NO ACK/NAK AFTER MESSAGE 486 | Start_T2_Timer(); 487 | } 488 | } 489 | 490 | #endregion 491 | 492 | //reserv for secs message only 493 | private void SendBytes(byte[] data) 494 | { 495 | System.Diagnostics.Debug.Print("SendBytes [" + GetHexString(data) + "]"); 496 | 497 | //append message to queue 498 | AddSecsMessageToBlockQueueing(data); 499 | 500 | if (m_State == CommuState.Idle) 501 | { 502 | RequestToSend(); 503 | } 504 | 505 | } 506 | 507 | private void RequestToSend() 508 | { 509 | Stop_T2_Timer(); 510 | m_State = CommuState.Send_Request; 511 | SendHandshakeCode(HandshakeCodes.ENQ); 512 | //1. NO EOT AFTER BID (ENQ) 513 | Start_T2_Timer(); 514 | } 515 | 516 | private void AddSecsMessageToBlockQueueing(byte[] secsMessageBytes) 517 | { 518 | lock (m_Locker) 519 | { 520 | 521 | int index = 0; 522 | int byteToRead = 0; 523 | 524 | byte[] header = new byte[10]; 525 | Array.Copy(secsMessageBytes, 0, header, 0, header.Length); 526 | 527 | //The R-bit is set to 0 for messages to the equipment and set to 1 for messages to the host 528 | header[0] = (byte)(header[0] & 0x7F); 529 | 530 | ushort blockNo = 0; 531 | bool isLastBlock; 532 | byte[] msgBlock; 533 | 534 | int remainingBodyByteCount = secsMessageBytes.Length - 10; 535 | 536 | //245 = Maximum byte of Body in each time 537 | int sendTimes = (remainingBodyByteCount == 0 ? 1 : (int)Math.Ceiling((double)(remainingBodyByteCount) / 245d)); 538 | 539 | System.Diagnostics.Debug.Print("AddSecsMessageToBlockQueueing {0} block(s)", sendTimes); 540 | 541 | index = 10; //skip header 542 | 543 | for (int i = 0; i < sendTimes; i++) 544 | { 545 | blockNo += 1; 546 | 547 | if (remainingBodyByteCount >= 245) 548 | { 549 | byteToRead = 245; 550 | } 551 | else 552 | { 553 | byteToRead = remainingBodyByteCount; //exclude header 554 | } 555 | 556 | msgBlock = new byte[byteToRead + 13];// LTH + header + body + sum 557 | //LTH 558 | msgBlock[0] = (byte)(msgBlock.Length - 3); 559 | //header 560 | Array.Copy(header, 0, msgBlock, 1, header.Length); 561 | 562 | if (byteToRead > 0) 563 | { 564 | // destination index 11 > LTH + header 565 | Array.Copy(secsMessageBytes, index, msgBlock, 11, byteToRead); 566 | index += byteToRead; 567 | remainingBodyByteCount -= byteToRead; 568 | } 569 | 570 | //modify BLOCK NO section in header 571 | isLastBlock = (remainingBodyByteCount == 0); 572 | byte[] blockNoBytes = BitConverter.GetBytes(blockNo); 573 | Array.Reverse(blockNoBytes); 574 | //BLOCK NO 575 | msgBlock[5] = (byte)(isLastBlock ? 576 | (blockNoBytes[0] | 0x80): 577 | (blockNoBytes[0] & 0x7F)); 578 | msgBlock[6] = blockNoBytes[1]; 579 | 580 | //SUM 581 | ushort checksum = 0; 582 | 583 | for (int j = 1; j < msgBlock.Length - 2; j++) //-2 exclude check sum 584 | { 585 | checksum += msgBlock[j]; 586 | } 587 | 588 | byte[] sumBytes = BitConverter.GetBytes(checksum); 589 | Array.Reverse(sumBytes); 590 | //11 = LTH + HEADER length 591 | Array.Copy(sumBytes, 0, msgBlock, msgBlock.Length - 2, 2); 592 | m_QueueSendingBlock.Enqueue(msgBlock); 593 | } 594 | } 595 | } 596 | 597 | private void SendHandshakeCode(HandshakeCodes chr) 598 | { 599 | 600 | System.Diagnostics.Debug.Print("SendControlChar := {0}", chr); 601 | 602 | byte[] b = null; 603 | switch (chr) 604 | { 605 | case HandshakeCodes.ACK: 606 | b = m_ACK; 607 | break; 608 | case HandshakeCodes.ENQ: 609 | b = m_ENQ; 610 | break; 611 | case HandshakeCodes.EOT: 612 | b = m_EOT; 613 | break; 614 | case HandshakeCodes.NAK: 615 | b = m_NAK; 616 | break; 617 | } 618 | 619 | if (b != null) 620 | { 621 | m_Port.Write(b, 0, b.Length); 622 | } 623 | 624 | } 625 | 626 | #endregion 627 | } 628 | } 629 | -------------------------------------------------------------------------------- /SecsGem/SecsIIMessageParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | using System.IO; 6 | 7 | namespace XtraLibrary.SecsGem 8 | { 9 | public class SecsIIMessageParser 10 | :SecsMessageParserBase 11 | { 12 | 13 | public SecsIIMessageParser() 14 | : base() 15 | { 16 | } 17 | 18 | public override SecsMessageBase ToSecsMessage(byte[] data) 19 | { 20 | using (MemoryStream reader = new MemoryStream(data)) 21 | { 22 | reader.Position = 0; 23 | 24 | byte[] lengthBytes = new byte[4]; 25 | 26 | //get length byte 27 | reader.Read(lengthBytes, 0, lengthBytes.Length); 28 | Array.Reverse(lengthBytes); 29 | 30 | int dataLength = BitConverter.ToInt32(lengthBytes, 0); 31 | if (data.Length != dataLength + 4) 32 | { 33 | //invalid data length 34 | throw new Exception("Invalid data lenght"); 35 | } 36 | 37 | //get header 38 | byte[] header = new byte[10]; 39 | reader.Read(header, 0, header.Length); 40 | 41 | //get device id from header 42 | byte[] deviceIdBytes = new byte[2]; 43 | Array.Copy(header, 0, deviceIdBytes, 0, 2); 44 | Array.Reverse(deviceIdBytes); 45 | ushort deviceId = BitConverter.ToUInt16(deviceIdBytes, 0); 46 | 47 | //get stream 48 | byte stream = (byte)(header[2] & 0x7F); 49 | byte function = header[3]; 50 | 51 | bool needReply = ((header[2] & 0x80) == 0x80); 52 | 53 | //transactionId. 54 | byte[] transactionIdBytes = new byte[4]; 55 | Array.Copy(header, 6, transactionIdBytes, 0, transactionIdBytes.Length); 56 | Array.Reverse(transactionIdBytes); 57 | uint transactionId = BitConverter.ToUInt32(transactionIdBytes, 0); 58 | 59 | SecsMessageBase msg = GetSecsMessageInstance(stream, function, needReply); 60 | 61 | msg.ReadItems(reader); //Sec2 data read 62 | msg.NeedReply = needReply; 63 | msg.TransactionId = transactionId; 64 | msg.DeviceId = deviceId; 65 | 66 | return msg; 67 | } 68 | } 69 | 70 | public override byte[] GetBytes(SecsMessageBase message) 71 | { 72 | byte[] headerBytes = new byte[10]; 73 | //device id ** let system manage 74 | byte[] deviceIdBytes = BitConverter.GetBytes(message.DeviceId); 75 | Array.Reverse(deviceIdBytes); 76 | 77 | headerBytes[0] = deviceIdBytes[0]; 78 | headerBytes[1] = deviceIdBytes[1]; 79 | //stream and w-bit 80 | if (message.NeedReply) 81 | { 82 | headerBytes[2] = (byte)(message.Stream | 0x80); 83 | } 84 | else 85 | { 86 | headerBytes[2] = (byte)(message.Stream & 0x7F); 87 | } 88 | //function 89 | headerBytes[3] = message.Function; 90 | //ptype 91 | headerBytes[4] = 0; 92 | //stype 93 | headerBytes[5] = 0; //0 - mean to "SescSessionType.Message" 94 | //transaction id ** let system manage 95 | 96 | byte[] transactionIdBytes = BitConverter.GetBytes(message.TransactionId); 97 | Array.Reverse(transactionIdBytes); 98 | 99 | headerBytes[6] = transactionIdBytes[0]; 100 | headerBytes[7] = transactionIdBytes[1]; 101 | headerBytes[8] = transactionIdBytes[2]; 102 | headerBytes[9] = transactionIdBytes[3]; 103 | 104 | List itemArray = new List(); 105 | 106 | int itemByteCount = 0; 107 | 108 | byte[] tmp1; 109 | foreach (SecsItem item in message.Items) 110 | { 111 | tmp1 = item.ToBytes(); 112 | itemArray.Add(tmp1); 113 | itemByteCount += tmp1.Length; 114 | } 115 | 116 | byte[] lengthBytes = BitConverter.GetBytes(headerBytes.Length + itemByteCount); //4-byte integer 117 | 118 | Array.Reverse(lengthBytes); 119 | 120 | byte[] allBytes = new byte[lengthBytes.Length + headerBytes.Length + itemByteCount]; 121 | 122 | int index = 0; 123 | 124 | Array.Copy(lengthBytes, 0, allBytes, 0, lengthBytes.Length); 125 | index += lengthBytes.Length; 126 | 127 | Array.Copy(headerBytes, 0, allBytes, lengthBytes.Length, headerBytes.Length); 128 | index += headerBytes.Length; 129 | 130 | byte[] tmp2; 131 | for (int i = 0; i < itemArray.Count; i++) 132 | { 133 | tmp2 = itemArray[i]; 134 | Array.Copy(tmp2, 0, allBytes, index, tmp2.Length); 135 | index += tmp2.Length; 136 | } 137 | 138 | itemArray.Clear(); 139 | 140 | return allBytes; 141 | } 142 | 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /SecsGem/SecsIMessageParser.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | using System.IO; 6 | 7 | namespace XtraLibrary.SecsGem 8 | { 9 | public class SecsIMessageParser 10 | :SecsMessageParserBase 11 | { 12 | public override SecsMessageBase ToSecsMessage(byte[] data) 13 | { 14 | byte[] header = new byte[10]; 15 | Array.Copy(data, 0, header, 0, header.Length); 16 | //header 17 | //[0][1][2][3][4][5][6][7][8][9] ... 18 | //[0][1] 19 | byte[] tmp2bytes = new byte[2]; 20 | Array.Copy(header, 0, tmp2bytes, 0, tmp2bytes.Length); 21 | Array.Reverse(tmp2bytes); 22 | ushort deviceId = BitConverter.ToUInt16(tmp2bytes, 0); 23 | // [2] 24 | byte stream = (byte)(header[2] & 0x7F); //0111 1111 25 | bool needReply = (0x80 == (byte)(header[2] & 0x80)); 26 | // [3] 27 | byte function = header[3]; 28 | bool isPrimary = (function % 2 == 1); 29 | // [4][5] 30 | Array.Copy(header, 4, tmp2bytes, 0, tmp2bytes.Length); 31 | bool isLastBlock = (0x80 == (tmp2bytes[0] & 0x80)); 32 | Array.Reverse(tmp2bytes); //reverse for convert by BitConvertor 33 | tmp2bytes[0] = (byte)(tmp2bytes[0] & 0x7F); 34 | ushort blockNo = BitConverter.ToUInt16(tmp2bytes, 0); 35 | // [6][7][8][9] 36 | byte[] temp4Bytes = new byte[4]; 37 | Array.Copy(header, 6, temp4Bytes, 0, temp4Bytes.Length); 38 | Array.Reverse(temp4Bytes); 39 | uint transId = BitConverter.ToUInt32(temp4Bytes, 0); 40 | 41 | SecsMessageBase msg = GetSecsMessageInstance(stream, function, needReply); 42 | 43 | if (data != null && data.Length > 10) 44 | { 45 | using (MemoryStream reader = new MemoryStream(data)) 46 | { 47 | reader.Position = header.Length; 48 | msg.ReadItems(reader); 49 | } 50 | } 51 | 52 | msg.TransactionId = transId; 53 | msg.DeviceId = deviceId; 54 | 55 | return msg; 56 | } 57 | 58 | public override byte[] GetBytes(SecsMessageBase message) 59 | { 60 | byte[] headerBytes = new byte[10]; 61 | //device id ** let system manage 62 | byte[] deviceIdBytes = BitConverter.GetBytes(message.DeviceId); 63 | Array.Reverse(deviceIdBytes); 64 | 65 | headerBytes[0] = deviceIdBytes[0]; 66 | headerBytes[1] = deviceIdBytes[1]; 67 | //stream and w-bit 68 | if (message.NeedReply) 69 | { 70 | headerBytes[2] = (byte)(message.Stream | 0x80); 71 | } 72 | else 73 | { 74 | headerBytes[2] = (byte)(message.Stream & 0x7F); 75 | } 76 | //function 77 | headerBytes[3] = message.Function; 78 | //BLOCK NO 79 | headerBytes[4] = 0; 80 | headerBytes[5] = 0; 81 | //transaction id ** let system manage 82 | 83 | byte[] transactionIdBytes = BitConverter.GetBytes(message.TransactionId); 84 | Array.Reverse(transactionIdBytes); 85 | 86 | headerBytes[6] = transactionIdBytes[0]; 87 | headerBytes[7] = transactionIdBytes[1]; 88 | headerBytes[8] = transactionIdBytes[2]; 89 | headerBytes[9] = transactionIdBytes[3]; 90 | 91 | List itemArray = new List(); 92 | 93 | int itemByteCount = 0; 94 | 95 | byte[] tmp1; 96 | foreach (SecsItem item in message.Items) 97 | { 98 | tmp1 = item.ToBytes(); 99 | itemArray.Add(tmp1); 100 | itemByteCount += tmp1.Length; 101 | } 102 | 103 | byte[] allBytes = new byte[headerBytes.Length + itemByteCount]; 104 | 105 | int index = 0; 106 | 107 | Array.Copy(headerBytes, 0, allBytes, 0, headerBytes.Length); 108 | index += headerBytes.Length; 109 | 110 | byte[] tmp2; 111 | for (int i = 0; i < itemArray.Count; i++) 112 | { 113 | tmp2 = itemArray[i]; 114 | Array.Copy(tmp2, 0, allBytes, index, tmp2.Length); 115 | index += tmp2.Length; 116 | } 117 | 118 | itemArray.Clear(); 119 | 120 | return allBytes; 121 | } 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /SecsGem/SecsIParameters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsIParameters 9 | { 10 | private string m_PortName; 11 | private int m_BaudRate; 12 | private int m_RTY; 13 | private double m_T1_Interval; 14 | private double m_T2_Interval; 15 | private double m_T3_Interval; 16 | //private double m_T4_Interval; 17 | 18 | public SecsIParameters() 19 | { 20 | m_PortName = "COM1"; 21 | m_BaudRate = 9600; 22 | m_RTY = 3; 23 | m_T1_Interval = 0.5d; 24 | m_T2_Interval = 11; 25 | m_T3_Interval = 45; 26 | //m_T4_Interval = 45; 27 | } 28 | 29 | public double T1_Interval 30 | { 31 | get { return m_T1_Interval; } 32 | set 33 | { 34 | if (value < 0.1d || value > 10d) 35 | { 36 | throw new Exception("Value is out of range 0.1 - 10 secs"); 37 | } 38 | m_T1_Interval = value; 39 | } 40 | } 41 | 42 | public double T2_Interval 43 | { 44 | get { return m_T2_Interval; } 45 | set 46 | { 47 | if (value < 0.2d || value > 25d) 48 | { 49 | throw new Exception("Value is out of range 0.2 - 25 secs"); 50 | } 51 | m_T2_Interval = value; 52 | } 53 | } 54 | 55 | public double T3_Interval 56 | { 57 | get { return m_T3_Interval; } 58 | set 59 | { 60 | if (value < 1d || value > 120d) 61 | { 62 | throw new Exception("Value is out of range 1 - 120 secs"); 63 | } 64 | m_T3_Interval = value; 65 | } 66 | } 67 | 68 | public string PortName 69 | { 70 | get 71 | { 72 | return m_PortName; 73 | } 74 | set 75 | { 76 | m_PortName = value; 77 | } 78 | } 79 | 80 | public int BaudRate 81 | { 82 | get 83 | { 84 | return m_BaudRate; 85 | } 86 | set 87 | { 88 | m_BaudRate = value; 89 | } 90 | } 91 | 92 | //T4 no use !!!! 93 | /// 94 | /// The maximum number of send retries allowed 95 | /// 96 | public int RTY 97 | { 98 | get 99 | { 100 | return m_RTY; 101 | } 102 | set 103 | { 104 | if (value < 0d || value > 31d) 105 | { 106 | throw new Exception("Value is out of range 0 - 31"); 107 | } 108 | m_RTY = value; 109 | } 110 | } 111 | 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /SecsGem/SecsItem.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | using System.IO; 6 | 7 | namespace XtraLibrary.SecsGem 8 | { 9 | public abstract class SecsItem 10 | { 11 | private string m_Name; 12 | public string Name 13 | { 14 | get { return m_Name; } 15 | } 16 | 17 | protected object m_Value; 18 | public object Value 19 | { 20 | get { return m_Value; } 21 | set 22 | { 23 | m_Value = value; 24 | } 25 | } 26 | 27 | private FormatCode m_Format; 28 | public FormatCode Format 29 | { 30 | get { return m_Format; } 31 | } 32 | 33 | /// 34 | /// Data include header and length byte 35 | /// 36 | /// 37 | public abstract byte[] ToBytes(); 38 | 39 | internal SecsItem(FormatCode fm, string name) 40 | : this(fm, name, null) 41 | { 42 | } 43 | 44 | internal SecsItem(FormatCode fm, string name, object value) 45 | { 46 | m_Format = fm; 47 | m_Name = name; 48 | m_Value = value; 49 | } 50 | 51 | public abstract void Read(MemoryStream reader); 52 | 53 | } 54 | 55 | public abstract class SecsItem:SecsItem 56 | { 57 | public new T Value 58 | { 59 | get { return (T)m_Value; } 60 | set 61 | { 62 | m_Value = value; 63 | } 64 | } 65 | 66 | public override void Read(MemoryStream reader) 67 | { 68 | byte[] formatCode = new byte[1]; 69 | //read for check 70 | reader.Read(formatCode, 0, formatCode.Length); 71 | 72 | byte lengthByteLong = 0; 73 | FormatCode code = FormatCodeHelper.GetFormatCode(formatCode[0], out lengthByteLong); 74 | 75 | if (this.Format != code) 76 | { 77 | //wrong format : throw exception 78 | throw new Exception("User defined is " + this.Format .ToString() + 79 | " but data format is " + code.ToString()); 80 | } 81 | 82 | byte[] readLengthByte = new byte[lengthByteLong]; 83 | reader.Read(readLengthByte, 0, readLengthByte.Length); 84 | 85 | //readLengthByte { 03, 5C, 9A } 86 | //prefer { 9A, 5C, 03, 00 } 87 | 88 | //temp { 0, 0, 0, 0} 89 | byte[] temp = new byte[4]; 90 | 91 | //temp { 0, 03, 5C, 9A} 92 | Array.Copy(readLengthByte, 0, temp, temp.Length - readLengthByte.Length, readLengthByte.Length); 93 | 94 | //temp { 9A, 5C, 03, 00} 95 | Array.Reverse(temp); 96 | 97 | uint byteToRead = BitConverter.ToUInt32(temp, 0); 98 | 99 | //System.Diagnostics.Debug.Print("Format := " + code.ToString() + ", Length := " + byteToRead.ToString()); 100 | 101 | ReadValue(reader, byteToRead); 102 | } 103 | 104 | protected abstract void ReadValue(MemoryStream reader, uint byteToRead); 105 | 106 | public SecsItem(FormatCode fm, string name) 107 | : base(fm, name) 108 | { 109 | 110 | } 111 | 112 | public SecsItem(FormatCode fm, string name, T val) 113 | : base(fm, name, val) 114 | { 115 | } 116 | 117 | /// 118 | /// Only [Data] except item header [ FormatCode ][Length Byte Long][Data] 119 | /// 120 | /// [Data] array 121 | protected abstract byte[] GetDataBytes(); 122 | 123 | /// 124 | /// For LIST only 125 | /// 126 | /// 127 | protected virtual int GetListItemLength() { 128 | return 0; 129 | } 130 | 131 | public override byte[] ToBytes() 132 | { 133 | 134 | byte[] data = GetDataBytes(); 135 | 136 | uint lengthByteOrElementCount = checked( 137 | (Format == FormatCode.LIST) ? (uint)GetListItemLength() : 138 | (data != null) ? (uint)data.Length : 0); 139 | //** in case of LIST lengt byte long determine bye item count 140 | 141 | //length byte long 142 | byte lbl = 0; 143 | if (lengthByteOrElementCount == 0 || lengthByteOrElementCount <= 0xFF) 144 | { 145 | lbl = 1; 146 | } 147 | else if (lengthByteOrElementCount <= 0xFFFF) 148 | { 149 | lbl = 2; 150 | } 151 | else if (lengthByteOrElementCount <= 0xFFFFFF) 152 | { 153 | lbl = 3; 154 | } 155 | else 156 | { 157 | throw new Exception("Data length is over " + (0xFFFFFF).ToString()); 158 | } 159 | 160 | byte[] itemBytes = new byte[1 + lbl + (data != null ? data.Length : 0)]; // 1 = format code byte 161 | 162 | int index = 0; 163 | //Format Code 164 | itemBytes[index] = (byte)(((byte)Format << 2) | lbl); 165 | index = +1; //1 byte format code 166 | 167 | //length byte 168 | //if btr = 10 169 | byte[] lengthByte = BitConverter.GetBytes(lengthByteOrElementCount); 170 | //lengthByte = [0x0A, 0x00, 0x00, 0x00] 171 | Array.Reverse(lengthByte); 172 | //lengthByte = [0x00, 0x00, 0x00, 0x0A] 173 | Array.Copy(lengthByte, lengthByte.Length - lbl, itemBytes, index, lbl); 174 | index += lbl; //length byte long 175 | //data 176 | if (data != null && data.Length > 0) 177 | { 178 | Array.Copy(data, 0, itemBytes, index, data.Length); 179 | } 180 | return itemBytes; 181 | } 182 | } 183 | } 184 | -------------------------------------------------------------------------------- /SecsGem/SecsItemAscii.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsItemAscii :SecsItem 9 | { 10 | 11 | public SecsItemAscii(string name) 12 | : base(FormatCode.ASCII, name, null) 13 | { 14 | } 15 | 16 | public SecsItemAscii(string name, string val) 17 | : base(FormatCode.ASCII, name, val) 18 | { 19 | } 20 | 21 | protected override void ReadValue(System.IO.MemoryStream reader, uint byteToRead) 22 | { 23 | byte[] buff = new byte[byteToRead]; 24 | reader.Read(buff, 0, buff.Length); 25 | this.Value = Encoding.ASCII.GetString(buff, 0, buff.Length); 26 | } 27 | 28 | protected override byte[] GetDataBytes() 29 | { 30 | if (this.Value == null) 31 | { 32 | return new byte[0]; 33 | } 34 | else 35 | { 36 | return Encoding.ASCII.GetBytes(this.Value); 37 | } 38 | } 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /SecsGem/SecsItemBinary.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsItemBinary :SecsItem 9 | { 10 | public SecsItemBinary(string name) 11 | : base(FormatCode.Binary, name, null) 12 | { 13 | } 14 | 15 | public SecsItemBinary(string name, params byte[] val) 16 | : base(FormatCode.Binary, name, val) 17 | { 18 | } 19 | 20 | protected override void ReadValue(System.IO.MemoryStream reader, uint byteToRead) 21 | { 22 | byte[] buff = new byte[byteToRead]; 23 | reader.Read(buff, 0, buff.Length); 24 | this.Value = buff; 25 | } 26 | 27 | protected override byte[] GetDataBytes() 28 | { 29 | return this.Value; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /SecsGem/SecsItemBoolean.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsItemBoolean :SecsItem 9 | { 10 | 11 | public SecsItemBoolean(string name) 12 | : base (FormatCode.Boolean, name, null) { 13 | } 14 | 15 | public SecsItemBoolean(string name, params bool[] val) 16 | : base(FormatCode.Boolean, name, val) 17 | { 18 | } 19 | 20 | protected override void ReadValue(System.IO.MemoryStream reader, uint byteToRead) 21 | { 22 | byte[] buff = new byte[byteToRead]; 23 | reader.Read(buff, 0, buff.Length); 24 | 25 | bool[] vals = new bool[byteToRead]; 26 | for (int i = 0; i < buff.Length; i++ ) 27 | { 28 | vals[i] = BitConverter.ToBoolean(buff, i); 29 | } 30 | 31 | this.Value = vals; // 160708 \783 Return Null 32 | 33 | } 34 | 35 | protected override byte[] GetDataBytes() 36 | { 37 | bool[] vals = this.Value; 38 | 39 | if (vals == null || vals.Length == 0) 40 | { 41 | return null; 42 | } 43 | 44 | byte[] buff = new byte[Value.Length]; 45 | for (int i = 0; i < buff.Length; i++) 46 | { 47 | buff[i] = BitConverter.GetBytes(vals[i])[0]; 48 | } 49 | return buff; 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /SecsGem/SecsItemF4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace XtraLibrary.SecsGem 6 | { 7 | public class SecsItemF4:SecsItem 8 | { 9 | public SecsItemF4(string name) 10 | : base(FormatCode.F4, name, null) //160711 \783 Error fix 11 | { 12 | 13 | } 14 | 15 | public SecsItemF4(string name, params float[] val) 16 | : base(FormatCode.F4, name, val) //160711 \783 Error fix 17 | { 18 | 19 | } 20 | 21 | protected override byte[] GetDataBytes() 22 | { 23 | 24 | float[] vals = this.Value; 25 | 26 | if (vals == null || vals.Length == 0) 27 | { 28 | //zero length item 29 | return null; 30 | } 31 | 32 | uint byteCount = checked((uint)(sizeof(float) * vals.Length)); 33 | byte[] data = new byte[byteCount]; 34 | 35 | byte[] valByte; 36 | int index = 0; 37 | foreach (float v in vals) 38 | { 39 | valByte = BitConverter.GetBytes(v); 40 | Array.Reverse(valByte); 41 | Array.Copy(valByte, 0, data, index, valByte.Length); 42 | index += valByte.Length; 43 | } 44 | 45 | return data; 46 | } 47 | 48 | protected override void ReadValue(System.IO.MemoryStream reader, uint byteToRead) 49 | { 50 | byte[] data = new byte[byteToRead]; 51 | reader.Read(data, 0, data.Length); 52 | 53 | //warning if devine result has fracment 54 | int valSizeInByte = sizeof(float); 55 | int valCount = (data.Length / valSizeInByte); 56 | 57 | float[] vals = new float[valCount]; 58 | 59 | int index = 0; 60 | byte[] temp = new byte[valSizeInByte]; 61 | for (int i = 0; i < valCount; i++) 62 | { 63 | Array.Copy(data, index, temp, 0, temp.Length); 64 | Array.Reverse(temp); 65 | 66 | vals[i] = BitConverter.ToSingle(temp, 0); 67 | index += valSizeInByte; 68 | } 69 | this.Value = vals; // 160711 \783 Add Return Value 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SecsGem/SecsItemF8.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsItemF8:SecsItem 9 | { 10 | public SecsItemF8(string name) 11 | : base(FormatCode.F8, name, null) 12 | { 13 | 14 | } 15 | 16 | public SecsItemF8(string name, params double[] val) 17 | :base(FormatCode.F8, name, val) { 18 | 19 | } 20 | 21 | protected override byte[] GetDataBytes() 22 | { 23 | 24 | double[] vals = this.Value; 25 | 26 | if (vals == null || vals.Length == 0) 27 | { 28 | //zero length item 29 | return null; 30 | } 31 | 32 | uint byteCount = checked((uint)(sizeof(double) * vals.Length)); 33 | byte[] data = new byte[byteCount]; 34 | 35 | byte[] valByte; 36 | int index = 0; 37 | foreach (double v in vals) 38 | { 39 | valByte = BitConverter.GetBytes(v); 40 | Array.Reverse(valByte); 41 | Array.Copy(valByte, 0, data, index, valByte.Length); 42 | index += valByte.Length; 43 | } 44 | 45 | return data; 46 | } 47 | 48 | protected override void ReadValue(System.IO.MemoryStream reader, uint byteToRead) 49 | { 50 | byte[] data = new byte[byteToRead]; 51 | reader.Read(data, 0, data.Length); 52 | 53 | //warning if devine result has fracment 54 | int valSizeInByte = sizeof(double); 55 | int valCount = (data.Length / valSizeInByte); 56 | 57 | double[] vals = new double[valCount]; 58 | 59 | int index = 0; 60 | byte[] temp = new byte[valSizeInByte]; 61 | for (int i = 0; i < valCount; i++) 62 | { 63 | Array.Copy(data, index, temp, 0, temp.Length); 64 | Array.Reverse(temp); 65 | 66 | vals[i] = BitConverter.ToDouble(temp, 0); 67 | index += valSizeInByte; 68 | } 69 | this.Value = vals; // 160711 \783 Add Return Value 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SecsGem/SecsItemFactory.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsItemFactory 9 | { 10 | public static SecsItem Create(string name, FormatCode format) 11 | { 12 | SecsItem item = null; 13 | 14 | switch (format) 15 | { 16 | case FormatCode.ASCII: 17 | item = new SecsItemAscii(name); 18 | break; 19 | case FormatCode.Binary: 20 | item = new SecsItemBinary(name); 21 | break; 22 | case FormatCode.Boolean: 23 | item = new SecsItemBoolean(name); 24 | break; 25 | case FormatCode.MC: 26 | break; 27 | case FormatCode.F4: 28 | item = new SecsItemF4(name); 29 | break; 30 | case FormatCode.F8: 31 | item = new SecsItemF8(name); 32 | break; 33 | case FormatCode.I1: 34 | item = new SecsItemI1(name); 35 | break; 36 | case FormatCode.I2: 37 | item = new SecsItemI2(name); 38 | break; 39 | case FormatCode.I4: 40 | item = new SecsItemI4(name); 41 | break; 42 | case FormatCode.I8: 43 | item = new SecsItemI8(name); 44 | break; 45 | case FormatCode.JIS8: 46 | break; 47 | case FormatCode.LIST: 48 | item = new SecsItemList(name); 49 | break; 50 | case FormatCode.U1: 51 | item = new SecsItemU1(name); 52 | break; 53 | case FormatCode.U2: 54 | item = new SecsItemU2(name); 55 | break; 56 | case FormatCode.U4: 57 | item = new SecsItemU4(name); 58 | break; 59 | case FormatCode.U8: 60 | item = new SecsItemU8(name); 61 | break; 62 | default : 63 | throw new Exception("Not support item format code"); 64 | } 65 | 66 | return item; 67 | } 68 | 69 | /// 70 | /// Create SecsItem by value typs { U1, U2, U4, U8, I1, I2, I4, I8, F4, F8 } 71 | /// 72 | /// SecsItem name 73 | /// value 74 | /// SecsItem 75 | public static SecsItem Create(string name, object numericValue) 76 | { 77 | Type valueType = numericValue.GetType(); 78 | 79 | return Create(name, valueType, numericValue); 80 | } 81 | 82 | public static SecsItem Create(string name, Type valueType) 83 | { 84 | return Create(name, valueType, Activator.CreateInstance(valueType)); 85 | } 86 | 87 | public static SecsItem Create(string name, Type valueType, object numericValue) 88 | { 89 | SecsItem item = null; 90 | 91 | if (valueType.Equals(typeof(byte))) 92 | { 93 | item = new SecsItemU1(name, new byte[] { (byte)numericValue }); 94 | } 95 | else if (valueType.Equals(typeof(byte[]))) 96 | { 97 | item = new SecsItemU1(name, (byte[])numericValue); 98 | } 99 | else if (valueType.Equals(typeof(ushort))) 100 | { 101 | item = new SecsItemU2(name, new ushort[] { (ushort)numericValue }); 102 | } 103 | else if (valueType.Equals(typeof(ushort[]))) 104 | { 105 | item = new SecsItemU2(name, (ushort[])numericValue); 106 | } 107 | else if (valueType.Equals(typeof(uint))) 108 | { 109 | item = new SecsItemU4(name, new uint[] { (uint)numericValue }); 110 | } 111 | else if (valueType.Equals(typeof(uint[]))) 112 | { 113 | item = new SecsItemU4(name, (uint[])numericValue); 114 | } 115 | else if (valueType.Equals(typeof(ulong))) 116 | { 117 | item = new SecsItemU8(name, new ulong[] { (ulong)numericValue }); 118 | } 119 | else if (valueType.Equals(typeof(ulong[]))) 120 | { 121 | item = new SecsItemU8(name, (ulong[])numericValue); 122 | } 123 | else if (valueType.Equals(typeof(sbyte))) 124 | { 125 | item = new SecsItemI1(name, new sbyte[] { (sbyte)numericValue }); 126 | } 127 | else if (valueType.Equals(typeof(sbyte[]))) 128 | { 129 | item = new SecsItemI1(name, (sbyte[])numericValue); 130 | } 131 | else if (valueType.Equals(typeof(short))) 132 | { 133 | item = new SecsItemI2(name, new short[] { (short)numericValue }); 134 | } 135 | else if (valueType.Equals(typeof(short[]))) 136 | { 137 | item = new SecsItemI2(name, (short[])numericValue); 138 | } 139 | else if (valueType.Equals(typeof(int))) 140 | { 141 | item = new SecsItemI4(name, new int[] { (int)numericValue }); 142 | } 143 | else if (valueType.Equals(typeof(int[]))) 144 | { 145 | item = new SecsItemI4(name, (int[])numericValue); 146 | } 147 | else if (valueType.Equals(typeof(long))) 148 | { 149 | item = new SecsItemI8(name, new long[] { (long)numericValue }); 150 | } 151 | else if (valueType.Equals(typeof(long[]))) 152 | { 153 | item = new SecsItemI8(name, (long[])numericValue); 154 | } 155 | else if (valueType.Equals(typeof(float))) 156 | { 157 | item = new SecsItemF4(name, new float[] { (float)numericValue }); 158 | } 159 | else if (valueType.Equals(typeof(float[]))) 160 | { 161 | item = new SecsItemF4(name, (float[])numericValue); 162 | } 163 | else if (valueType.Equals(typeof(double))) 164 | { 165 | item = new SecsItemF8(name, new double[] { (double)numericValue }); 166 | } 167 | else if (valueType.Equals(typeof(double[]))) 168 | { 169 | item = new SecsItemF8(name, (double[])numericValue); 170 | } 171 | else 172 | { 173 | throw new Exception("Not supported value type :" + valueType.Name); 174 | } 175 | return item; 176 | } 177 | 178 | private SecsItemFactory() { 179 | } 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /SecsGem/SecsItemI1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsItemI1:SecsItem 9 | { 10 | 11 | public SecsItemI1(string name) 12 | : base(FormatCode.I1, name, null) 13 | { 14 | } 15 | 16 | public SecsItemI1(string name, params sbyte[] val) 17 | : base(FormatCode.I1, name, val) 18 | { 19 | } 20 | 21 | protected override void ReadValue(System.IO.MemoryStream reader, uint byteToRead) 22 | { 23 | byte[] buff = new byte[byteToRead]; 24 | reader.Read(buff, 0, buff.Length); 25 | unchecked 26 | { 27 | this.Value = new sbyte[buff.Length]; 28 | for (int i = 0; i < buff.Length; i++) 29 | { 30 | this.Value[i] = (sbyte)buff[i]; 31 | } 32 | } 33 | } 34 | 35 | protected override byte[] GetDataBytes() 36 | { 37 | sbyte[] vals = this.Value; 38 | 39 | if (vals == null || vals.Length == 0) 40 | { 41 | //zero length item 42 | return null; 43 | } 44 | 45 | byte[] buff = new byte[vals.Length]; 46 | unchecked 47 | { 48 | for (int i = 0; i < buff.Length; i++) 49 | { 50 | buff[i] = (byte)vals[i]; 51 | } 52 | } 53 | return buff; 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /SecsGem/SecsItemI2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsItemI2 :SecsItem 9 | { 10 | public SecsItemI2(string name) 11 | : base(FormatCode.I2, name, null) 12 | { 13 | } 14 | 15 | public SecsItemI2(string name, params short[] val) 16 | : base(FormatCode.I2, name, val) 17 | { 18 | } 19 | 20 | protected override byte[] GetDataBytes() 21 | { 22 | 23 | short[] vals = this.Value; 24 | 25 | if (vals == null || vals.Length == 0) 26 | { 27 | //zero length item 28 | return null; 29 | } 30 | 31 | uint byteCount = checked((uint)(sizeof(short) * vals.Length)); 32 | byte[] data = new byte[byteCount]; 33 | 34 | byte[] valByte; 35 | int index = 0; 36 | foreach (short v in vals) 37 | { 38 | valByte = BitConverter.GetBytes(v); 39 | Array.Reverse(valByte); 40 | Array.Copy(valByte, 0, data, index, valByte.Length); 41 | index += valByte.Length; 42 | } 43 | 44 | return data; 45 | } 46 | 47 | protected override void ReadValue(System.IO.MemoryStream reader, uint byteToRead) 48 | { 49 | byte[] data = new byte[byteToRead]; 50 | reader.Read(data, 0, data.Length); 51 | 52 | //warning if devine result has fracment 53 | int valSizeInByte = sizeof(short); 54 | int valCount = (data.Length / valSizeInByte); 55 | 56 | short[] vals = new short[valCount]; 57 | 58 | int index = 0; 59 | byte[] temp = new byte[valSizeInByte]; 60 | for (int i = 0; i < valCount; i++) 61 | { 62 | Array.Copy(data, index, temp, 0, temp.Length); 63 | Array.Reverse(temp); 64 | 65 | vals[i] = BitConverter.ToInt16(temp, 0); 66 | index += valSizeInByte; 67 | } 68 | 69 | this.Value = vals; 70 | 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /SecsGem/SecsItemI4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsItemI4 :SecsItem 9 | { 10 | public SecsItemI4(string name) 11 | : base(FormatCode.I4, name, null) 12 | { 13 | } 14 | 15 | public SecsItemI4(string name, params int[] val) 16 | : base(FormatCode.I4, name, val) 17 | { 18 | } 19 | 20 | protected override byte[] GetDataBytes() 21 | { 22 | 23 | int[] vals = this.Value; 24 | 25 | if (vals == null || vals.Length == 0) 26 | { 27 | //zero length item 28 | return null; 29 | } 30 | 31 | uint byteCount = checked((uint)(sizeof(int) * vals.Length)); 32 | byte[] data = new byte[byteCount]; 33 | 34 | byte[] valByte; 35 | int index = 0; 36 | foreach (int v in vals) 37 | { 38 | valByte = BitConverter.GetBytes(v); 39 | Array.Reverse(valByte); 40 | Array.Copy(valByte, 0, data, index, valByte.Length); 41 | index += valByte.Length; 42 | } 43 | 44 | return data; 45 | } 46 | 47 | protected override void ReadValue(System.IO.MemoryStream reader, uint byteToRead) 48 | { 49 | byte[] data = new byte[byteToRead]; 50 | reader.Read(data, 0, data.Length); 51 | 52 | //warning if devine result has fracment 53 | int valSizeInByte = sizeof(int ); 54 | int valCount = (data.Length / valSizeInByte); 55 | 56 | int[] vals = new int[valCount]; 57 | 58 | int index = 0; 59 | byte[] temp = new byte[valSizeInByte]; 60 | for (int i = 0; i < valCount; i++) 61 | { 62 | Array.Copy(data, index, temp, 0, temp.Length); 63 | Array.Reverse(temp); 64 | 65 | vals[i] = BitConverter.ToInt32(temp, 0); 66 | index += valSizeInByte; 67 | } 68 | 69 | this.Value = vals; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SecsGem/SecsItemI8.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsItemI8 :SecsItem 9 | { 10 | public SecsItemI8(string name) 11 | : base(FormatCode.I8, name, null) 12 | { 13 | } 14 | 15 | public SecsItemI8(string name, params long[] val) 16 | : base(FormatCode.I8, name, val) 17 | { 18 | } 19 | 20 | protected override byte[] GetDataBytes() 21 | { 22 | 23 | long[] vals = this.Value; 24 | 25 | if (vals == null || vals.Length == 0) 26 | { 27 | //zero length item 28 | return null; 29 | } 30 | 31 | uint byteCount = checked((uint)(sizeof(long) * vals.Length)); 32 | byte[] data = new byte[byteCount]; 33 | 34 | byte[] valByte; 35 | int index = 0; 36 | foreach (long v in vals) 37 | { 38 | valByte = BitConverter.GetBytes(v); 39 | Array.Reverse(valByte); 40 | Array.Copy(valByte, 0, data, index, valByte.Length); 41 | index += valByte.Length; 42 | } 43 | 44 | return data; 45 | } 46 | 47 | protected override void ReadValue(System.IO.MemoryStream reader, uint byteToRead) 48 | { 49 | byte[] data = new byte[byteToRead]; 50 | reader.Read(data, 0, data.Length); 51 | 52 | //warning if devine result has fracment 53 | int valSizeInByte = sizeof(long); 54 | int valCount = (data.Length / valSizeInByte); 55 | 56 | long[] vals = new long[valCount]; 57 | 58 | int index = 0; 59 | byte[] temp = new byte[valSizeInByte]; 60 | for (int i = 0; i < valCount; i++) 61 | { 62 | Array.Copy(data, index, temp, 0, temp.Length); 63 | Array.Reverse(temp); 64 | 65 | vals[i] = BitConverter.ToInt64(temp, 0); 66 | index += valSizeInByte; 67 | } 68 | 69 | this.Value = vals; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SecsGem/SecsItemList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | using System.Collections; 6 | 7 | namespace XtraLibrary.SecsGem 8 | { 9 | public class SecsItemList:SecsItem> 10 | { 11 | 12 | public SecsItemList(string name) 13 | : base(FormatCode.LIST, name, new List()) 14 | { 15 | } 16 | 17 | protected override void ReadValue(System.IO.MemoryStream reader, uint itemToRead) 18 | { 19 | List elements = this.Value; 20 | 21 | if (elements.Count == 0) //not fixed item list 22 | { 23 | long readItemCount = 0; 24 | 25 | byte[] formatCodeByte = new byte[1]; 26 | byte lenghtByteLong = 0; 27 | 28 | FormatCode fc; 29 | SecsItem item = null; 30 | 31 | while (readItemCount < itemToRead) 32 | { 33 | reader.Read(formatCodeByte, 0, formatCodeByte.Length); 34 | 35 | //move back to format code position 36 | reader.Position -= formatCodeByte.Length; 37 | 38 | fc = FormatCodeHelper.GetFormatCode(formatCodeByte[0], out lenghtByteLong); 39 | item = SecsItemFactory.Create("DV" + elements.Count.ToString(), fc); 40 | item.Read(reader); 41 | elements.Add(item); 42 | readItemCount += 1; 43 | } //while (readItemCount < itemToRead) 44 | } 45 | else if (itemToRead == elements.Count) //fixed item list 46 | { 47 | //class defination error 48 | foreach (SecsItem item in elements) 49 | { 50 | item.Read(reader); 51 | } 52 | } 53 | else 54 | { 55 | //invalid define 56 | throw new Exception("Defined item count is not equal to item to read"); 57 | } 58 | 59 | } 60 | 61 | protected override int GetListItemLength() 62 | { 63 | return this.Value.Count; 64 | } 65 | 66 | protected override byte[] GetDataBytes() 67 | { 68 | List elements = this.Value ; 69 | List itemBytesList = new List(); 70 | 71 | long totalByte = 0; 72 | byte[] tmp; 73 | foreach (SecsItem item in elements) 74 | { 75 | tmp = item.ToBytes(); 76 | totalByte += tmp.LongLength; 77 | itemBytesList.Add(tmp); 78 | } 79 | 80 | byte[] data = new byte[totalByte]; 81 | long index = 0; 82 | 83 | for (int i = 0; i < itemBytesList.Count; i++) 84 | { 85 | tmp = itemBytesList[i]; 86 | Array.Copy(tmp, 0, data, index, tmp.Length); 87 | index += tmp.Length ; 88 | } 89 | 90 | itemBytesList.Clear(); 91 | itemBytesList = null; 92 | 93 | return data; 94 | } 95 | 96 | #region "For easy to use" 97 | 98 | public void AddItem(SecsItem item) 99 | { 100 | this.Value.Add(item); 101 | } 102 | 103 | public void Clear() 104 | { 105 | this.Value.Clear(); 106 | } 107 | 108 | #endregion 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /SecsGem/SecsItemMultiByteChar.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsItemMultiByteChar : SecsItem 9 | { 10 | 11 | public SecsItemMultiByteChar(string name) 12 | : base(FormatCode.MC, name) 13 | { 14 | } 15 | 16 | public SecsItemMultiByteChar(string name, string val) 17 | : base(FormatCode.MC, name, val) 18 | { 19 | } 20 | 21 | public enum EncodingType :ushort 22 | { 23 | None = 0, 24 | ISO_10646_UCS_2 = 1, 25 | UTF8 = 2, 26 | ISO_646_1991 = 3, 27 | ISO_8859_1 = 4, 28 | ISO_8859_11 = 5, 29 | TIS_620 = 6, 30 | IS_13194 = 7, 31 | ShiftJIS = 8, 32 | Japanese_EUC_JP = 9, 33 | Korean_EUC_KR = 10, 34 | SimplifiedChinese_GB = 11, 35 | SimplifiedChinese_EUC_CN = 12, 36 | TraditionalChinese_Big5 = 13, 37 | TraditionalChinese_EUC_TW = 14 38 | } 39 | 40 | private EncodingType m_TextEncodType; 41 | public EncodingType TextEncodType 42 | { 43 | get { return m_TextEncodType; } 44 | set 45 | { 46 | m_TextEncodType = value; 47 | } 48 | } 49 | 50 | protected override void ReadValue(System.IO.MemoryStream reader, uint byteToRead) 51 | { 52 | byte[] encoding = new byte[2]; //2 byte after encoding 53 | reader.Read(encoding, 0, encoding.Length); 54 | 55 | try 56 | { 57 | m_TextEncodType = (EncodingType)BitConverter.ToUInt16(encoding, 0); 58 | } 59 | catch 60 | { 61 | //unknow encoding 62 | } 63 | 64 | byte[] data = new byte[byteToRead - encoding.Length]; 65 | reader.Read(data, 0, data.Length); 66 | } 67 | 68 | protected override byte[] GetDataBytes() 69 | { 70 | string vals = this.Value; 71 | 72 | if (vals == null || vals.Length == 0) 73 | { 74 | //zero length item 75 | return null; 76 | } 77 | 78 | byte[] encoding = new byte[2]; 79 | byte[] textBytes = null; 80 | 81 | byte[] data = new byte[encoding.Length + textBytes.Length]; 82 | Array.Copy(encoding, 0, data, 0, encoding.Length); 83 | Array.Copy(textBytes, 0, data, encoding.Length, textBytes.Length); 84 | 85 | return data; 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /SecsGem/SecsItemU1.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsItemU1 :SecsItem 9 | { 10 | 11 | public SecsItemU1(string name) 12 | : base(FormatCode.U1, name, null) 13 | { 14 | } 15 | 16 | public SecsItemU1(string name, params byte[] val) 17 | : base(FormatCode.U1, name, val) 18 | { 19 | } 20 | 21 | protected override byte[] GetDataBytes() 22 | { 23 | 24 | byte[] vals = this.Value; 25 | 26 | if (vals == null || vals.Length == 0) 27 | { 28 | //zero length item 29 | return null; 30 | } 31 | 32 | return vals; 33 | } 34 | 35 | protected override void ReadValue(System.IO.MemoryStream reader, uint byteToRead) 36 | { 37 | byte[] data = new byte[byteToRead]; 38 | reader.Read(data, 0, data.Length); 39 | this.Value = data; 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /SecsGem/SecsItemU2.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace XtraLibrary.SecsGem 6 | { 7 | public class SecsItemU2 :SecsItem 8 | { 9 | 10 | public SecsItemU2(string name) 11 | : base(FormatCode.U2, name, null) 12 | { 13 | } 14 | 15 | public SecsItemU2(string name, params ushort[] val) 16 | : base(FormatCode.U2, name, val) 17 | { 18 | } 19 | 20 | protected override byte[] GetDataBytes() 21 | { 22 | 23 | ushort[] vals = this.Value; 24 | 25 | if (vals == null || vals.Length == 0) 26 | { 27 | //zero length item 28 | return null; 29 | } 30 | 31 | uint byteCount = checked((uint)(sizeof(ushort) * vals.Length)); 32 | byte[] data = new byte[byteCount]; 33 | 34 | byte[] valByte; 35 | int index = 0; 36 | foreach (ushort v in vals) 37 | { 38 | valByte = BitConverter.GetBytes(v); 39 | Array.Reverse(valByte); 40 | Array.Copy(valByte, 0, data, index, valByte.Length); 41 | index += valByte.Length; 42 | } 43 | 44 | return data; 45 | } 46 | 47 | protected override void ReadValue(System.IO.MemoryStream reader, uint byteToRead) 48 | { 49 | byte[] data = new byte[byteToRead]; 50 | reader.Read(data, 0, data.Length); 51 | 52 | //warning if devine result has fracment 53 | int valSizeInByte = sizeof(ushort); 54 | int valCount = (data.Length / valSizeInByte); 55 | 56 | ushort[] vals = new ushort[valCount]; 57 | 58 | int index = 0; 59 | byte[] temp = new byte[valSizeInByte]; 60 | for (int i = 0; i < valCount; i++) 61 | { 62 | Array.Copy(data, index, temp, 0, temp.Length); 63 | Array.Reverse(temp); 64 | 65 | vals[i] = BitConverter.ToUInt16(temp, 0); 66 | index += valSizeInByte; 67 | } 68 | 69 | this.Value = vals; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SecsGem/SecsItemU4.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsItemU4 :SecsItem 9 | { 10 | 11 | public SecsItemU4(string name) 12 | : base(FormatCode.U4, name, null) 13 | { 14 | } 15 | 16 | public SecsItemU4(string name, params uint[] val) 17 | : base(FormatCode.U4, name, val) 18 | { 19 | } 20 | 21 | protected override byte[] GetDataBytes() 22 | { 23 | 24 | uint[] vals = this.Value; 25 | 26 | if (vals == null || vals.Length == 0) 27 | { 28 | //zero length item 29 | return null; 30 | } 31 | 32 | uint byteCount = checked((uint)(sizeof(uint) * vals.Length)); 33 | byte[] data = new byte[byteCount]; 34 | 35 | byte[] valByte; 36 | int index = 0; 37 | foreach (uint v in vals) 38 | { 39 | valByte = BitConverter.GetBytes(v); 40 | Array.Reverse(valByte); 41 | Array.Copy(valByte, 0, data, index, valByte.Length); 42 | index += valByte.Length; 43 | } 44 | 45 | return data; 46 | } 47 | 48 | protected override void ReadValue(System.IO.MemoryStream reader, uint byteToRead) 49 | { 50 | byte[] data = new byte[byteToRead]; 51 | reader.Read(data, 0, data.Length); 52 | 53 | //warning if devine result has fracment 54 | int valSizeInByte = sizeof(uint); 55 | int valCount = (data.Length / valSizeInByte); 56 | 57 | uint[] vals = new uint[valCount]; 58 | 59 | int index = 0; 60 | byte[] temp = new byte[valSizeInByte]; 61 | for (int i = 0; i < valCount; i++) 62 | { 63 | Array.Copy(data, index, temp, 0, temp.Length); 64 | Array.Reverse(temp); 65 | 66 | vals[i] = BitConverter.ToUInt32(temp, 0); 67 | index += valSizeInByte; 68 | } 69 | 70 | this.Value = vals; 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /SecsGem/SecsItemU8.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsItemU8:SecsItem 9 | { 10 | public SecsItemU8(string name) 11 | : base(FormatCode.U8, name, null) 12 | { 13 | } 14 | 15 | public SecsItemU8(string name, params ulong[] val) 16 | : base(FormatCode.U8, name, val) 17 | { 18 | } 19 | 20 | protected override byte[] GetDataBytes() 21 | { 22 | 23 | ulong[] vals = this.Value; 24 | 25 | if (vals == null || vals.Length == 0) 26 | { 27 | //zero length item 28 | return null; 29 | } 30 | 31 | uint byteCount = checked((uint)(sizeof(ulong) * vals.Length)); 32 | byte[] data = new byte[byteCount]; 33 | 34 | byte[] valByte; 35 | int index = 0; 36 | foreach (ulong v in vals) 37 | { 38 | valByte = BitConverter.GetBytes(v); 39 | Array.Reverse(valByte); 40 | Array.Copy(valByte, 0, data, index, valByte.Length); 41 | index += valByte.Length; 42 | } 43 | 44 | return data; 45 | } 46 | 47 | protected override void ReadValue(System.IO.MemoryStream reader, uint byteToRead) 48 | { 49 | byte[] data = new byte[byteToRead]; 50 | reader.Read(data, 0, data.Length); 51 | 52 | //warning if devine result has fracment 53 | int valSizeInByte = sizeof(ulong); 54 | int valCount = (data.Length / valSizeInByte); 55 | 56 | ulong[] vals = new ulong[valCount]; 57 | 58 | int index = 0; 59 | byte[] temp = new byte[valSizeInByte]; 60 | for (int i = 0; i < valCount; i++) 61 | { 62 | Array.Copy(data, index, temp, 0, temp.Length); 63 | Array.Reverse(temp); 64 | 65 | vals[i] = BitConverter.ToUInt64(temp, 0); 66 | index += valSizeInByte; 67 | } 68 | 69 | this.Value = vals; 70 | } 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /SecsGem/SecsMessage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | /// 9 | /// Common SecsMessage : this class can not be inherite 10 | /// 11 | public sealed class SecsMessage :SecsMessageBase 12 | { 13 | public SecsMessage(byte s, byte f, bool w) 14 | :base(s, f, w) 15 | { 16 | } 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /SecsGem/SecsMessageBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | using System.Collections; 6 | using System.IO; 7 | 8 | namespace XtraLibrary.SecsGem 9 | { 10 | public abstract class SecsMessageBase 11 | { 12 | List m_Items; 13 | private byte m_Stream; 14 | private byte m_Function; 15 | private bool m_NeedReply; 16 | private uint m_TransactionId; 17 | private ushort m_DeviceId; 18 | 19 | #region "Properties" 20 | 21 | public byte Stream 22 | { 23 | get { return m_Stream; } 24 | internal set 25 | { 26 | m_Stream = value; 27 | } 28 | } 29 | 30 | public byte Function 31 | { 32 | get { return m_Function; } 33 | internal set 34 | { 35 | m_Function = value; 36 | } 37 | } 38 | 39 | public bool NeedReply 40 | { 41 | get { return m_NeedReply; } 42 | internal set 43 | { 44 | m_NeedReply = value; 45 | } 46 | } 47 | 48 | public uint TransactionId 49 | { 50 | get { 51 | return m_TransactionId; 52 | } 53 | set 54 | { 55 | m_TransactionId = value; 56 | } 57 | } 58 | 59 | public List Items 60 | { 61 | get { 62 | return m_Items; 63 | } 64 | } 65 | 66 | 67 | public ushort DeviceId 68 | { 69 | get { return m_DeviceId; } 70 | set 71 | { 72 | m_DeviceId = value; 73 | } 74 | } 75 | 76 | 77 | #endregion 78 | 79 | #region "Protected methods" 80 | 81 | /// 82 | /// Create new Item 83 | /// 84 | /// Stream 85 | /// Function 86 | /// W-Bit : if true it mean need reply message 87 | protected SecsMessageBase(byte s, byte f, bool w) 88 | { 89 | m_Stream = s; 90 | m_Function = f; 91 | m_NeedReply = w; 92 | m_Items = new List(); 93 | m_TransactionId = 0; 94 | } 95 | 96 | /// 97 | /// Incase of Secondary message 98 | /// 99 | /// Primary Message 100 | protected SecsMessageBase(SecsMessageBase priMsg) 101 | :this(priMsg.Stream, (byte)(priMsg.Function + 1), false) 102 | { 103 | m_TransactionId = priMsg.TransactionId; 104 | m_DeviceId = priMsg.DeviceId; 105 | } 106 | 107 | /// 108 | /// Add secs item 109 | /// 110 | /// secs item 111 | protected void AddItem(SecsItem item) 112 | { 113 | if (!m_Items.Contains(item)) 114 | { 115 | m_Items.Add(item); 116 | } 117 | } 118 | 119 | /// 120 | /// Add Level 1 Item 121 | /// 122 | /// name of the parameter 123 | /// item type 124 | /// 125 | protected SecsItem AddItem(string name, Type itemType) 126 | { 127 | if (!itemType.IsSubclassOf(typeof(SecsItem)) || (!itemType.IsAbstract)) 128 | { 129 | //not support 130 | throw new Exception("Invalide item type"); 131 | } 132 | 133 | SecsItem item = (SecsItem)Activator.CreateInstance(itemType, name); 134 | AddItem(item); 135 | 136 | return item; 137 | } 138 | 139 | #endregion 140 | 141 | #region "Internal methods" 142 | 143 | public void ReadItems(MemoryStream reader) 144 | { 145 | //if developer did not define item of this message 146 | if (m_Items.Count == 0) 147 | { 148 | byte[] formatCodeByte = new byte[1]; 149 | SecsItem item; 150 | FormatCode fc; 151 | byte lenghtByteLong; 152 | 153 | while (reader.Position < reader.Length) 154 | { 155 | reader.Read(formatCodeByte, 0, formatCodeByte.Length); 156 | 157 | //move back to format code position because *1 158 | reader.Position -= formatCodeByte.Length; 159 | 160 | fc = FormatCodeHelper.GetFormatCode(formatCodeByte[0], out lenghtByteLong); 161 | item = SecsItemFactory.Create("DV" + m_Items.Count.ToString(), fc); 162 | //*1 this function is read format code also 163 | item.Read(reader); 164 | 165 | AddItem(item); 166 | } 167 | } 168 | //if developer already defined item of this message 169 | else if (m_Items.Count > 0) 170 | { 171 | foreach (SecsItem item in m_Items) 172 | { 173 | item.Read(reader); 174 | } 175 | } 176 | } 177 | 178 | #endregion 179 | 180 | } 181 | 182 | } 183 | -------------------------------------------------------------------------------- /SecsGem/SecsMessageParserBase.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public abstract class SecsMessageParserBase 9 | { 10 | public abstract SecsMessageBase ToSecsMessage(byte[] data); 11 | public abstract byte[] GetBytes(SecsMessageBase msg); 12 | 13 | private Dictionary> m_RegisterCustomTypeDict; 14 | 15 | protected SecsMessageParserBase() { 16 | m_RegisterCustomTypeDict = new Dictionary>(); 17 | } 18 | 19 | protected SecsMessageBase GetSecsMessageInstance(byte stream, byte function, bool needReply) 20 | { 21 | Dictionary dict; 22 | Type msgType; 23 | SecsMessageBase msg = null; 24 | if (m_RegisterCustomTypeDict.TryGetValue(stream, out dict) 25 | && dict.TryGetValue(function, out msgType)) 26 | { 27 | msg = (SecsMessageBase)Activator.CreateInstance(msgType); 28 | } 29 | else 30 | { 31 | msg = new SecsMessage(stream, function, needReply); 32 | } 33 | 34 | return msg; 35 | } 36 | 37 | /// 38 | /// In case of UserDefined class that inherit SecsMessageBase 39 | /// and want to Parser to convert to UserDefined type instead of SecsMessage 40 | /// 41 | /// UserDefined type that inherited from SecsMessageBase 42 | public void RegisterCustomSecsMessage(Type messageType) 43 | { 44 | 45 | try 46 | { 47 | 48 | 49 | if (messageType.IsSubclassOf(typeof(SecsMessageBase)) && 50 | !messageType.IsAbstract) 51 | { 52 | 53 | 54 | 55 | 56 | SecsMessageBase tmp = (SecsMessageBase)Activator.CreateInstance(messageType); 57 | Dictionary dict; 58 | 59 | if (!m_RegisterCustomTypeDict.TryGetValue(tmp.Stream, out dict)) 60 | { 61 | dict = new Dictionary(); 62 | dict.Add(tmp.Function, messageType); 63 | m_RegisterCustomTypeDict.Add(tmp.Stream, dict); 64 | } 65 | else 66 | { 67 | if (dict.ContainsKey(tmp.Function)) 68 | { 69 | //replace the same function 70 | dict.Remove(tmp.Function); 71 | } 72 | dict.Add(tmp.Function, messageType); 73 | } 74 | 75 | } 76 | 77 | 78 | 79 | } 80 | catch 81 | { 82 | throw new Exception("RegisterCustomSecsMessage Error"); // 160715 \783 Catch RegiserSecsCustom 83 | 84 | } 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | } 97 | 98 | 99 | 100 | 101 | } 102 | 103 | } 104 | -------------------------------------------------------------------------------- /SecsGem/SecsReport.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsReport 9 | { 10 | public void AddStatusVariable(object svid) 11 | { 12 | 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /SecsGem/SecsTransaction.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class SecsTransaction 9 | { 10 | 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /SecsGem/SmlBuilder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | using System.IO; 6 | 7 | namespace XtraLibrary.SecsGem 8 | { 9 | public class SmlBuilder 10 | { 11 | private SmlBuilder() { } 12 | 13 | #region "Convert SecsMessageBase to SML" 14 | 15 | public static string ToSmlString(SecsMessageBase msg) 16 | { 17 | StringBuilder sb = new StringBuilder(); 18 | sb.Append(string.Format("S{0}F{1} {2} [TID:={3}]", msg.Stream, msg.Function,(msg.NeedReply ? " W" : ""), msg.TransactionId)); 19 | 20 | foreach (SecsItem item in msg.Items) 21 | { 22 | GetItemValueAsString(sb, item, 1); 23 | } 24 | 25 | string ret = sb.ToString(); 26 | sb.Remove(0, sb.Length); 27 | 28 | return ret; 29 | } 30 | 31 | public static string GetItemFormatString(FormatCode fc) 32 | { 33 | string ret = ""; 34 | 35 | switch (fc) 36 | { 37 | case FormatCode.ASCII: 38 | ret = "A"; 39 | break; 40 | case FormatCode.Binary : 41 | ret = "B"; 42 | break; 43 | case FormatCode.Boolean: 44 | ret = "TF"; 45 | break; 46 | case FormatCode.LIST: 47 | ret = "L"; 48 | break; 49 | case FormatCode.MC: 50 | ret = "C2"; 51 | break; 52 | case FormatCode.F4: 53 | case FormatCode.F8 : 54 | case FormatCode.I1: 55 | case FormatCode.I2 : 56 | case FormatCode.I4: 57 | case FormatCode.I8: 58 | case FormatCode.JIS8: 59 | case FormatCode.U1: 60 | case FormatCode.U2: 61 | case FormatCode.U4: 62 | case FormatCode.U8 : 63 | ret = fc.ToString(); 64 | break; 65 | } 66 | 67 | return ret; 68 | } 69 | 70 | public static string GetSecsItemValue(SecsItem item) 71 | { 72 | StringBuilder sb = new StringBuilder(); 73 | 74 | if ((item is SecsItemAscii) || (item is SecsItemMultiByteChar)) 75 | { 76 | sb.Append("\"" + (string)item.Value + "\""); 77 | } 78 | else if (item is SecsItemBoolean) 79 | { 80 | GetItem_Boolean_ValueAsString(sb, (SecsItemBoolean)item); 81 | } 82 | else if (item is SecsItemBinary) 83 | { 84 | GetItem_Binary_ValueAsString(sb, (SecsItemBinary)item); 85 | } 86 | else if (item is SecsItemList) 87 | { 88 | //nothing to get 89 | } 90 | else if (item is SecsItemU1) 91 | { 92 | GetItem_U1_ValueAsString(sb, (SecsItemU1)item); 93 | } 94 | else if (item is SecsItemU2) 95 | { 96 | GetItem_U2_ValueAsString(sb, (SecsItemU2)item); 97 | } 98 | else if (item is SecsItemU4) 99 | { 100 | GetItem_U4_ValueAsString(sb, (SecsItemU4)item); 101 | } 102 | else if (item is SecsItemU8) 103 | { 104 | GetItem_U8_ValueAsString(sb, (SecsItemU8)item); 105 | } 106 | else if (item is SecsItemI1) 107 | { 108 | GetItem_I1_ValueAsString(sb, (SecsItemI1)item); 109 | } 110 | else if (item is SecsItemI2) 111 | { 112 | GetItem_I2_ValueAsString(sb, (SecsItemI2)item); 113 | } 114 | else if (item is SecsItemI4) 115 | { 116 | GetItem_I4_ValueAsString(sb, (SecsItemI4)item); 117 | } 118 | else if (item is SecsItemI8) 119 | { 120 | GetItem_I8_ValueAsString(sb, (SecsItemI8)item); 121 | } 122 | else if (item is SecsItemF4) 123 | { 124 | GetItem_F4_ValueAsString(sb, (SecsItemF4)item); 125 | } 126 | else if (item is SecsItemF8) 127 | { 128 | GetItem_F8_ValueAsString(sb, (SecsItemF8)item); 129 | } 130 | 131 | return sb.ToString(); 132 | } 133 | 134 | private static int GetItemLength(SecsItem item) 135 | { 136 | int ret = 0; 137 | 138 | if (item == null) 139 | { 140 | ret = 0; 141 | } 142 | else if (item.Value == null) 143 | { 144 | ret = 0; 145 | } 146 | else 147 | { 148 | Type t = item.Value.GetType(); 149 | if (t.IsArray) 150 | { 151 | ret = ((Array)(item.Value)).Length; 152 | } 153 | else if (item is SecsItemList) 154 | { 155 | ret = ((SecsItemList)item).Value.Count; 156 | } 157 | else if (item.Value is string) 158 | { 159 | ret = ((string)(item.Value)).Length; 160 | } 161 | } 162 | 163 | return ret; 164 | } 165 | 166 | private static void GetItemValueAsString(StringBuilder sb, SecsItem item, int tabCount) 167 | { 168 | sb.Append(Environment.NewLine); 169 | if (tabCount > 0) 170 | { 171 | sb.Append('\t', tabCount); 172 | } 173 | 174 | sb.Append(string.Format("< {0} [{1}] ", GetItemFormatString(item.Format), GetItemLength(item))); 175 | 176 | if ((item is SecsItemAscii) || (item is SecsItemMultiByteChar)) 177 | { 178 | sb.Append("\"" + (string)item.Value + "\""); 179 | } 180 | else if (item is SecsItemBoolean) 181 | { 182 | GetItem_Boolean_ValueAsString(sb, (SecsItemBoolean)item); 183 | } 184 | else if (item is SecsItemBinary) 185 | { 186 | GetItem_Binary_ValueAsString(sb, (SecsItemBinary)item); 187 | } 188 | else if (item is SecsItemList) 189 | { 190 | SecsItemList list = (SecsItemList)item; 191 | 192 | GetItem_List_ValueAsString(sb, list, tabCount + 1); 193 | 194 | if (list.Value.Count > 0) 195 | { 196 | sb.Append(Environment.NewLine); 197 | 198 | if (tabCount > 0) 199 | { 200 | sb.Append('\t', tabCount); 201 | } 202 | } 203 | 204 | } 205 | else if (item is SecsItemU1) 206 | { 207 | GetItem_U1_ValueAsString(sb, (SecsItemU1)item); 208 | } 209 | else if (item is SecsItemU2) 210 | { 211 | GetItem_U2_ValueAsString(sb, (SecsItemU2)item); 212 | } 213 | else if (item is SecsItemU4) 214 | { 215 | GetItem_U4_ValueAsString(sb, (SecsItemU4)item); 216 | } 217 | else if (item is SecsItemU8) 218 | { 219 | GetItem_U8_ValueAsString(sb, (SecsItemU8)item); 220 | } 221 | else if (item is SecsItemI1) 222 | { 223 | GetItem_I1_ValueAsString(sb, (SecsItemI1)item); 224 | } 225 | else if (item is SecsItemI2) 226 | { 227 | GetItem_I2_ValueAsString(sb, (SecsItemI2)item); 228 | } 229 | else if (item is SecsItemI4) 230 | { 231 | GetItem_I4_ValueAsString(sb, (SecsItemI4)item); 232 | } 233 | else if (item is SecsItemI8) 234 | { 235 | GetItem_I8_ValueAsString(sb, (SecsItemI8)item); 236 | } 237 | else if (item is SecsItemF4) 238 | { 239 | GetItem_F4_ValueAsString(sb, (SecsItemF4)item); 240 | } 241 | else if (item is SecsItemF8) 242 | { 243 | GetItem_F8_ValueAsString(sb, (SecsItemF8)item); 244 | } 245 | 246 | if (!(item is SecsItemList)) 247 | { 248 | sb.Append(" "); 249 | } 250 | sb.Append(">"); 251 | 252 | } 253 | 254 | private static void GetItem_List_ValueAsString(StringBuilder sb, SecsItemList item, int tabCount) 255 | { 256 | foreach (SecsItem subItem in item.Value) 257 | { 258 | GetItemValueAsString(sb, subItem, tabCount); 259 | } 260 | } 261 | 262 | private static void GetItem_Boolean_ValueAsString(StringBuilder sb, SecsItemBoolean item) 263 | { 264 | if (item.Value != null) 265 | { 266 | bool val; 267 | for (int i = 0; i < item.Value.Length; i++) 268 | { 269 | val = item.Value[i]; 270 | if (i == 0) 271 | { 272 | sb.Append(val.ToString()); 273 | } 274 | else 275 | { 276 | sb.Append(" " + val.ToString()); 277 | } 278 | } 279 | } 280 | } 281 | 282 | private static void GetItem_Binary_ValueAsString(StringBuilder sb, SecsItemBinary item) 283 | { 284 | if (item.Value != null) 285 | { 286 | byte val; 287 | for (int i = 0; i < item.Value.Length; i++) 288 | { 289 | val = item.Value[i]; 290 | if (i == 0) 291 | { 292 | sb.Append(val.ToString("X2")); 293 | } 294 | else 295 | { 296 | sb.Append(" " + val.ToString("X2")); 297 | } 298 | } 299 | } 300 | } 301 | 302 | private static void GetItem_U1_ValueAsString(StringBuilder sb, SecsItemU1 item) 303 | { 304 | if (item.Value != null) 305 | { 306 | byte val; 307 | for (int i = 0; i < item.Value.Length; i++) 308 | { 309 | val = item.Value[i]; 310 | if (i == 0) 311 | { 312 | sb.Append(val.ToString()); 313 | } 314 | else 315 | { 316 | sb.Append(" " + val.ToString()); 317 | } 318 | } 319 | } 320 | } 321 | 322 | private static void GetItem_U2_ValueAsString(StringBuilder sb, SecsItemU2 item) 323 | { 324 | if (item.Value != null) 325 | { 326 | ushort val; 327 | for (int i = 0; i < item.Value.Length; i++) 328 | { 329 | val = item.Value[i]; 330 | if (i == 0) 331 | { 332 | sb.Append(val.ToString()); 333 | } 334 | else 335 | { 336 | sb.Append(" " + val.ToString()); 337 | } 338 | } 339 | } 340 | } 341 | 342 | private static void GetItem_U4_ValueAsString(StringBuilder sb, SecsItemU4 item) 343 | { 344 | if (item.Value != null) 345 | { 346 | uint val; 347 | for (int i = 0; i < item.Value.Length; i++) 348 | { 349 | val = item.Value[i]; 350 | if (i == 0) 351 | { 352 | sb.Append(val.ToString()); 353 | } 354 | else 355 | { 356 | sb.Append(" " + val.ToString()); 357 | } 358 | } 359 | } 360 | } 361 | 362 | private static void GetItem_U8_ValueAsString(StringBuilder sb, SecsItemU8 item) 363 | { 364 | if (item.Value != null) 365 | { 366 | ulong val; 367 | for (int i = 0; i < item.Value.Length; i++) 368 | { 369 | val = item.Value[i]; 370 | if (i == 0) 371 | { 372 | sb.Append(val.ToString()); 373 | } 374 | else 375 | { 376 | sb.Append(" " + val.ToString()); 377 | } 378 | } 379 | } 380 | } 381 | 382 | private static void GetItem_I1_ValueAsString(StringBuilder sb, SecsItemI1 item) 383 | { 384 | if (item.Value != null) 385 | { 386 | sbyte val; 387 | for (int i = 0; i < item.Value.Length; i++) 388 | { 389 | val = item.Value[i]; 390 | if (i == 0) 391 | { 392 | sb.Append(val.ToString()); 393 | } 394 | else 395 | { 396 | sb.Append(" " + val.ToString()); 397 | } 398 | } 399 | } 400 | } 401 | 402 | private static void GetItem_I2_ValueAsString(StringBuilder sb, SecsItemI2 item) 403 | { 404 | if (item.Value != null) 405 | { 406 | short val; 407 | for (int i = 0; i < item.Value.Length; i++) 408 | { 409 | val = item.Value[i]; 410 | if (i == 0) 411 | { 412 | sb.Append(val.ToString()); 413 | } 414 | else 415 | { 416 | sb.Append(" " + val.ToString()); 417 | } 418 | } 419 | } 420 | } 421 | 422 | private static void GetItem_I4_ValueAsString(StringBuilder sb, SecsItemI4 item) 423 | { 424 | if (item.Value != null) 425 | { 426 | int val; 427 | for (int i = 0; i < item.Value.Length; i++) 428 | { 429 | val = item.Value[i]; 430 | if (i == 0) 431 | { 432 | sb.Append(val.ToString()); 433 | } 434 | else 435 | { 436 | sb.Append(" " + val.ToString()); 437 | } 438 | } 439 | } 440 | } 441 | 442 | private static void GetItem_I8_ValueAsString(StringBuilder sb, SecsItemI8 item) 443 | { 444 | if (item.Value != null) 445 | { 446 | long val; 447 | for (int i = 0; i < item.Value.Length; i++) 448 | { 449 | val = item.Value[i]; 450 | if (i == 0) 451 | { 452 | sb.Append(val.ToString()); 453 | } 454 | else 455 | { 456 | sb.Append(" " + val.ToString()); 457 | } 458 | } 459 | } 460 | } 461 | 462 | private static void GetItem_F4_ValueAsString(StringBuilder sb, SecsItemF4 item) 463 | { 464 | if (item.Value != null) 465 | { 466 | float val; 467 | for (int i = 0; i < item.Value.Length; i++) 468 | { 469 | val = item.Value[i]; 470 | if (i == 0) 471 | { 472 | sb.Append(val.ToString()); 473 | } 474 | else 475 | { 476 | sb.Append(" " + val.ToString()); 477 | } 478 | } 479 | } 480 | } 481 | 482 | private static void GetItem_F8_ValueAsString(StringBuilder sb, SecsItemF8 item) 483 | { 484 | if (item.Value != null) 485 | { 486 | double val; 487 | for (int i = 0; i < item.Value.Length; i++) 488 | { 489 | val = item.Value[i]; 490 | if (i == 0) 491 | { 492 | sb.Append(val.ToString()); 493 | } 494 | else 495 | { 496 | sb.Append(" " + val.ToString()); 497 | } 498 | } 499 | } 500 | } 501 | 502 | #endregion 503 | 504 | //not finished yet 505 | #region "Convert SML to SecsMessageBase" 506 | 507 | //******************************* 508 | //******** 2015-05-29 *********** 509 | //******************************* 510 | // S1F14 [TID:=2] 511 | // < L [2] 512 | // < B [1] 00 > 513 | // < L [2] 514 | // < A [9] "LT-VISION" > 515 | // < A [10] "3.05.08.66" > 516 | // > 517 | // > 518 | //******************************* 519 | 520 | //private SecsMessageBase ToSecsMessageBase(string sml) 521 | //{ 522 | // SecsMessageBase msg = null; 523 | // StringReader reader = new StringReader(sml); 524 | // char[] buff = new char[1]; 525 | // char c; 526 | // SecsItem currentItem = null; 527 | // string str = ""; 528 | 529 | // while (reader.Peek() > -1) 530 | // { 531 | // reader.Read(buff, 0, 1); 532 | // c = buff[0]; 533 | // switch (c) 534 | // { 535 | // case '<': 536 | // currentItem = null; 537 | // break; 538 | // case '>': 539 | // break; 540 | // case ' ': 541 | // break; 542 | // case '\t': 543 | // break; 544 | // case '[': 545 | // break; 546 | // default: 547 | // str = str + c; 548 | // break; 549 | // } 550 | // } 551 | // return msg; 552 | //} 553 | 554 | //private void GetItem_LIST_AsSecsItem(StringReader reader, SecsItemList currentItem) 555 | //{ 556 | 557 | //} 558 | 559 | private FormatCode GetItemFormatCode(string strFc) 560 | { 561 | FormatCode ret = FormatCode.LIST; 562 | 563 | switch (strFc) 564 | { 565 | case "A": 566 | ret = FormatCode.ASCII; 567 | break; 568 | case "B": 569 | ret = FormatCode.Binary; 570 | break; 571 | case "TF": 572 | ret = FormatCode.Boolean; 573 | break; 574 | case "L": 575 | ret = FormatCode.LIST; 576 | break; 577 | case "C2": 578 | ret = FormatCode.MC; 579 | break; 580 | case "F4": 581 | case "F8": 582 | case "I1": 583 | case "I2": 584 | case "I4": 585 | case "I8": 586 | case "JIS8": 587 | case "U1": 588 | case "U2": 589 | case "U4": 590 | case "U8": 591 | ret = (FormatCode)Enum.Parse(typeof(FormatCode), strFc); 592 | break; 593 | } 594 | 595 | return ret; 596 | } 597 | 598 | #endregion 599 | } 600 | } 601 | -------------------------------------------------------------------------------- /SecsGem/StatusVariable.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | public class StatusVariable 9 | { 10 | protected object m_ID; 11 | protected object m_Value; 12 | 13 | public object ID 14 | { 15 | get 16 | { 17 | return m_ID; 18 | } 19 | set 20 | { 21 | m_ID = value; 22 | } 23 | } 24 | 25 | public object Value 26 | { 27 | get 28 | { 29 | return m_Value; 30 | } 31 | set 32 | { 33 | m_Value = value; 34 | } 35 | } 36 | } 37 | 38 | public class StatusVariable 39 | : StatusVariable 40 | { 41 | public new T ID 42 | { 43 | get { 44 | return (T)m_ID; 45 | } 46 | set { 47 | m_ID = value; 48 | } 49 | } 50 | 51 | public new V Value 52 | { 53 | get { 54 | return (V)m_Value; 55 | } 56 | set 57 | { 58 | m_Value = value; 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /SecsGem/T3Timer.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | 4 | using System.Text; 5 | 6 | namespace XtraLibrary.SecsGem 7 | { 8 | internal class T3Timer 9 | : System.Timers.Timer 10 | { 11 | 12 | private uint m_TransactionId; 13 | 14 | public uint TransactionId 15 | { 16 | get 17 | { 18 | return m_TransactionId; 19 | } 20 | } 21 | 22 | internal T3Timer(uint tid) 23 | { 24 | m_TransactionId = tid; 25 | } 26 | 27 | } 28 | 29 | } 30 | -------------------------------------------------------------------------------- /Threading/TimedLock.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | using System.Threading; 5 | 6 | namespace XtraLibrary.Threading 7 | { 8 | public struct TimedLock: IDisposable 9 | { 10 | public static TimedLock Lock (object o) 11 | { 12 | return Lock (o, TimeSpan.FromSeconds (10)); 13 | } 14 | 15 | public static TimedLock Lock (object o, TimeSpan timeout) 16 | { 17 | TimedLock tl = new TimedLock (o); 18 | if (!Monitor.TryEnter(o, timeout)) 19 | { 20 | #if DEBUG 21 | System.GC.SuppressFinalize(tl.m_LeakDetector); 22 | #endif 23 | throw new LockTimeoutException (); 24 | } 25 | 26 | return tl; 27 | } 28 | 29 | private TimedLock (object o) 30 | { 31 | m_Target = o; 32 | #if DEBUG 33 | m_LeakDetector = new Sentinel(); 34 | #endif 35 | } 36 | private object m_Target; 37 | 38 | public void Dispose () 39 | { 40 | Monitor.Exit (m_Target); 41 | 42 | // It's a bad error if someone forgets to call Dispose, 43 | // so in Debug builds, we put a finalizer in to detect 44 | // the error. If Dispose is called, we suppress the 45 | // finalizer. 46 | #if DEBUG 47 | GC.SuppressFinalize(m_LeakDetector); 48 | #endif 49 | } 50 | 51 | #if DEBUG 52 | // (In Debug mode, we make it a class so that we can add a finalizer 53 | // in order to detect when the object is not freed.) 54 | private class Sentinel 55 | { 56 | ~Sentinel() 57 | { 58 | // If this finalizer runs, someone somewhere failed to 59 | // call Dispose, which means we've failed to leave 60 | // a monitor! 61 | System.Diagnostics.Debug.Fail("Undisposed lock"); 62 | } 63 | } 64 | private Sentinel m_LeakDetector; 65 | #endif 66 | 67 | } 68 | public class LockTimeoutException : ApplicationException 69 | { 70 | public LockTimeoutException () : base("Timeout waiting for lock") 71 | { 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /XtraLibrary.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Debug 5 | AnyCPU 6 | 9.0.30729 7 | 2.0 8 | {4C1D8AAA-F229-4058-9BEF-E0041DF1F9BF} 9 | Library 10 | Properties 11 | XtraLibrary 12 | XtraLibrary 13 | v2.0 14 | 512 15 | 16 | 17 | 3.5 18 | 19 | 20 | 21 | true 22 | full 23 | false 24 | bin\Debug\ 25 | DEBUG;TRACE 26 | prompt 27 | 4 28 | 29 | 30 | pdbonly 31 | true 32 | bin\Release\ 33 | TRACE 34 | prompt 35 | 4 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | Code 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | Component 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | Code 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | Code 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | Code 92 | 93 | 94 | Code 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 114 | -------------------------------------------------------------------------------- /XtraLibrary.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27004.2006 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XtraLibrary", "XtraLibrary.csproj", "{4C1D8AAA-F229-4058-9BEF-E0041DF1F9BF}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TestWinProject", "..\TestWinProject\TestWinProject.csproj", "{0FF6A0E2-052E-4870-B811-9D2EAD44253D}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Debug|Mixed Platforms = Debug|Mixed Platforms 14 | Debug|x86 = Debug|x86 15 | Release|Any CPU = Release|Any CPU 16 | Release|Mixed Platforms = Release|Mixed Platforms 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {4C1D8AAA-F229-4058-9BEF-E0041DF1F9BF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {4C1D8AAA-F229-4058-9BEF-E0041DF1F9BF}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {4C1D8AAA-F229-4058-9BEF-E0041DF1F9BF}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 23 | {4C1D8AAA-F229-4058-9BEF-E0041DF1F9BF}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 24 | {4C1D8AAA-F229-4058-9BEF-E0041DF1F9BF}.Debug|x86.ActiveCfg = Debug|Any CPU 25 | {4C1D8AAA-F229-4058-9BEF-E0041DF1F9BF}.Release|Any CPU.ActiveCfg = Release|Any CPU 26 | {4C1D8AAA-F229-4058-9BEF-E0041DF1F9BF}.Release|Any CPU.Build.0 = Release|Any CPU 27 | {4C1D8AAA-F229-4058-9BEF-E0041DF1F9BF}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 28 | {4C1D8AAA-F229-4058-9BEF-E0041DF1F9BF}.Release|Mixed Platforms.Build.0 = Release|Any CPU 29 | {4C1D8AAA-F229-4058-9BEF-E0041DF1F9BF}.Release|x86.ActiveCfg = Release|Any CPU 30 | {0FF6A0E2-052E-4870-B811-9D2EAD44253D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 31 | {0FF6A0E2-052E-4870-B811-9D2EAD44253D}.Debug|Any CPU.Build.0 = Debug|Any CPU 32 | {0FF6A0E2-052E-4870-B811-9D2EAD44253D}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 33 | {0FF6A0E2-052E-4870-B811-9D2EAD44253D}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 34 | {0FF6A0E2-052E-4870-B811-9D2EAD44253D}.Debug|x86.ActiveCfg = Debug|Any CPU 35 | {0FF6A0E2-052E-4870-B811-9D2EAD44253D}.Debug|x86.Build.0 = Debug|Any CPU 36 | {0FF6A0E2-052E-4870-B811-9D2EAD44253D}.Release|Any CPU.ActiveCfg = Release|Any CPU 37 | {0FF6A0E2-052E-4870-B811-9D2EAD44253D}.Release|Any CPU.Build.0 = Release|Any CPU 38 | {0FF6A0E2-052E-4870-B811-9D2EAD44253D}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 39 | {0FF6A0E2-052E-4870-B811-9D2EAD44253D}.Release|Mixed Platforms.Build.0 = Release|Any CPU 40 | {0FF6A0E2-052E-4870-B811-9D2EAD44253D}.Release|x86.ActiveCfg = Release|Any CPU 41 | {0FF6A0E2-052E-4870-B811-9D2EAD44253D}.Release|x86.Build.0 = Release|Any CPU 42 | EndGlobalSection 43 | GlobalSection(SolutionProperties) = preSolution 44 | HideSolutionNode = FALSE 45 | EndGlobalSection 46 | GlobalSection(ExtensibilityGlobals) = postSolution 47 | SolutionGuid = {30C594AF-AC9E-4728-8F0A-2D133CF25F99} 48 | EndGlobalSection 49 | EndGlobal 50 | -------------------------------------------------------------------------------- /app.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | --------------------------------------------------------------------------------