SerialPortUtilityPro.cs 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616
  1. using UnityEngine;
  2. using System.Runtime.InteropServices;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. #pragma warning disable 0414
  7. namespace SerialPortUtility
  8. {
  9. [System.Serializable]
  10. public class SPUPEventObject : UnityEngine.Events.UnityEvent<object> { }
  11. [System.Serializable]
  12. public class SPUPSystemEventObject : UnityEngine.Events.UnityEvent<SerialPortUtility.SerialPortUtilityPro, string> { }
  13. [StructLayout(LayoutKind.Sequential)]
  14. public class SPUPMudbusData
  15. {
  16. public byte Address;
  17. public byte Function;
  18. public byte[] Data;
  19. public SPUPMudbusData(byte addr, byte func, byte[] dat)
  20. {
  21. Address = addr;
  22. Function = func;
  23. Data = dat;
  24. }
  25. }
  26. [HelpURL("https://portutility.com")]
  27. #if UNITY_5_5_OR_NEWER
  28. [DefaultExecutionOrder(-100)]
  29. #endif
  30. [AddComponentMenu("SerialPort/SerialPort Utility Pro")]
  31. public class SerialPortUtilityPro : MonoBehaviour
  32. {
  33. //Version Infomation
  34. public const string VersionString = "2.51";
  35. //spapmain.cpp
  36. //SPAP snapConfig
  37. [StructLayout(LayoutKind.Sequential)]
  38. private struct SpapConfig
  39. {
  40. //Config
  41. public int BaudRate; //32bit x6
  42. public int Parity;
  43. public int StopBit;
  44. public int DataBit;
  45. public int DiscardNull;
  46. public int IgnoreBreakSignal;
  47. public int Skip;
  48. }
  49. //Define
  50. public enum OpenSystem
  51. {
  52. NumberOrder = 0,
  53. USB = 1,
  54. PCI = 2,
  55. BluetoothSSP = 3,
  56. TCPSerialEmulatorClient = 10,
  57. TCPSerialEmulatorServer = 11,
  58. }
  59. public enum MethodSystem
  60. {
  61. Streaming = 0,
  62. BinaryStreaming,
  63. LineFeedDataToString,
  64. LineFeedDataToBinary,
  65. FixedLengthDataToString,
  66. FixedLengthDataToBinary,
  67. SplitStringToArray,
  68. SplitStringToDictionary,
  69. SplitStringToGameObject,
  70. JSONToClassObject,
  71. ModbusASCII,
  72. ModbusRTU,
  73. }
  74. public enum ParityEnum
  75. {
  76. No = 0,
  77. Odd,
  78. Even,
  79. Mark,
  80. Space,
  81. }
  82. public enum StopBitEnum
  83. {
  84. OneBit = 0,
  85. TwoBit = 2,
  86. }
  87. public enum DataBitEnum
  88. {
  89. EightBit = 8,
  90. SevenBit = 7,
  91. }
  92. public enum SourcePath
  93. {
  94. AbsolutePath = 0,
  95. RelativeToStreamingAssetsFolder,
  96. RelativeToDataFolder,
  97. RelativeToPeristentDataFolder,
  98. }
  99. public enum UpdateMethod
  100. {
  101. Update,
  102. FixedUpdate,
  103. ManualUpdate,
  104. }
  105. //Variable : public
  106. //Config
  107. public bool IsAutoOpen = true;
  108. public OpenSystem OpenMethod = OpenSystem.USB;
  109. public MethodSystem ReadProtocol = MethodSystem.LineFeedDataToString;
  110. public string VendorID {
  111. set { this.VendorID_string = value; }
  112. get { return this.VendorID_string; }
  113. }
  114. public string ProductID
  115. {
  116. set { this.ProductID_string = value; }
  117. get { return this.ProductID_string; }
  118. }
  119. public string SerialNumber
  120. {
  121. set { this.SerialNumber_search_string = value; }
  122. get { return this.SerialNumber_search_string; }
  123. }
  124. public string IPAddress
  125. {
  126. set { this.VendorID_string = value; }
  127. get { return this.VendorID_string; }
  128. }
  129. public string Port
  130. {
  131. set { this.ProductID_string = System.Text.RegularExpressions.Regex.Replace(value, "[^0-9]", ""); }
  132. get { return this.ProductID_string; }
  133. }
  134. public string DeviceName
  135. {
  136. set { this.SerialNumber_search_string = value; }
  137. get { return this.SerialNumber_search_string; }
  138. }
  139. //Device infomation class
  140. public class DeviceInfo
  141. {
  142. public string Vendor;
  143. public string Product;
  144. public string SerialNumber;
  145. public string PortName;
  146. }
  147. //structure
  148. public int BaudRate = 9600;
  149. public ParityEnum Parity = ParityEnum.No;
  150. public StopBitEnum StopBit = StopBitEnum.OneBit;
  151. public DataBitEnum DataBit = DataBitEnum.EightBit;
  152. public bool RecvDiscardNull = false;
  153. public const bool RecvIgnoreBreakSignal = true;
  154. public bool AutoRTSCTSHandshake = false;
  155. public bool StartEnableDTR = true;
  156. public bool DtrEnabled = false;
  157. public bool RtsEnabled = false;
  158. public int Skip = 0;
  159. public bool BluetoothSSPNoServerMode = false;
  160. //read structure
  161. public string FeedCode = "<CR><LF>";
  162. public string SplitCode = ",";
  163. public int FixedFeedCount = 10;
  164. public UpdateMethod UpdateProcessing = UpdateMethod.Update;
  165. //Event
  166. public SPUPEventObject ReadCompleteEventObject = new SPUPEventObject();
  167. public string ReadCompleteEventObjectType = "";
  168. public GameObject ReadClassMembersObject = null;
  169. public SPUPSystemEventObject SystemEventObject = new SPUPSystemEventObject();
  170. //DebugString
  171. public string GetSerialDebugString {
  172. get { return SerialDebugString; }
  173. }
  174. public void SetDebugConsoleMonitorView(bool enable)
  175. {
  176. if (IsOpened())
  177. return;
  178. DebugConsoleMonitor = enable;
  179. }
  180. public SourcePath ExternalConfigPath = SourcePath.RelativeToStreamingAssetsFolder;
  181. public string ExternalConfigFileName = "serial_config.txt";
  182. //for inside system : private
  183. [SerializeField]
  184. private string VendorID_string = "1234";
  185. [SerializeField]
  186. private string ProductID_string = "1234";
  187. [SerializeField]
  188. private string SerialNumber_search_string = "";
  189. [SerializeField]
  190. private bool EnableTrans = true;
  191. [SerializeField]
  192. private bool DebugConsoleMonitor = false; //Debug Monitor
  193. [SerializeField]
  194. private bool ExternalConfig = false;
  195. //for Editor
  196. [SerializeField]
  197. private bool ExpandConfig = true;
  198. [SerializeField]
  199. private bool ExpandSPMonitor = false;
  200. [SerializeField]
  201. private bool ExpandEventConfig = false;
  202. private const int STRING_MAXBUFFER = 512;
  203. private const int SPAPHANDLE_ERROR = (-1);
  204. private const int SPAPHANDLE_PERMISSION = (-2);
  205. private const int SerialDebugStringMAX = 100;
  206. private const int READDATA_ERROR_DISCONNECT = (-1);
  207. private const int READDATA_ERROR_LICENSEEER = (-3);
  208. private List<byte> dataBuffer = new List<byte>();
  209. private bool RtsEnableSave = true;
  210. private int SerialPortHandle = SPAPHANDLE_ERROR;
  211. private string SerialDebugString = "";
  212. private GameObject DebugConsoleObject = null;
  213. private bool IsErrFinished = false;
  214. private bool IsOpenProcess = false;
  215. //equal code : system fixed
  216. private const string equalChar = "=";
  217. //DLL import
  218. ////////////// Main SPAP DLL System //////////////
  219. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  220. static extern int spapOpenUSB(string vId, string pId, string serial, SpapConfig config);
  221. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  222. static extern int spapOpenPCIe(string vId, string dId, string serial, SpapConfig config);
  223. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  224. static extern int spapOpenBtSPP(string search, bool isServer, SpapConfig config);
  225. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  226. static extern int spapOpenBtVCOM(string search, SpapConfig config);
  227. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  228. static extern int spapOpen(SpapConfig config);
  229. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  230. static extern int spapOpenSerialEmulatorTCP(string sendIP, string port);
  231. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  232. static extern void spapClose(int handle);
  233. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  234. static extern void spapShutDown();
  235. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  236. static extern int spapSetConfig(int handle, SpapConfig config);
  237. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  238. static extern SpapConfig spapGetConfig(int handle);
  239. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  240. static extern void spapWrite(int handle, System.IntPtr buffer, int bufferLength);
  241. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  242. static extern int spapReadDataAvailable(int handle);
  243. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  244. static extern int spapReadData(int handle, byte[] str, int str_size);
  245. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  246. static extern void spapSetDTR(int handle, bool enable);
  247. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  248. static extern void spapSetRTS(int handle, bool enable);
  249. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  250. static extern bool spapGetDTR(int handle);
  251. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  252. static extern bool spapGetRTS(int handle);
  253. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  254. static extern bool spapGetDSR(int handle);
  255. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  256. static extern bool spapGetCTS(int handle);
  257. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  258. static extern void spapBreakSignal(int handle, bool enable);
  259. //List
  260. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  261. static extern int spapDeviceListAvailable();
  262. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  263. static extern int spapDeviceList(int deviceNum, [MarshalAs(UnmanagedType.LPStr)]System.Text.StringBuilder deviceInfo, int buffer_size);
  264. //License System
  265. [DllImport("spap", CharSet = CharSet.Ansi, CallingConvention = CallingConvention.Cdecl)]
  266. static extern void spapIsLicensed([MarshalAs(UnmanagedType.LPStr)]StringBuilder email, [MarshalAs(UnmanagedType.LPStr)]StringBuilder code, int size);
  267. private static bool licensecheck = true; //asset
  268. public string LicenseEmail = "";
  269. public string LicenseCode = "";
  270. //Android Object
  271. #if UNITY_ANDROID && !UNITY_EDITOR
  272. private static AndroidJavaObject _androidPlugin = null;
  273. #endif
  274. //Start
  275. void Start()
  276. {
  277. IsOpenProcess = false;
  278. SerialPortHandle = SPAPHANDLE_ERROR;
  279. IsErrFinished = false;
  280. #if UNITY_ANDROID && !UNITY_EDITOR
  281. // Plugin
  282. if (_androidPlugin == null) _androidPlugin = new AndroidJavaObject("com.wizapply.libspap.spap");
  283. // Get Context(Activity) Object
  284. AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
  285. AndroidJavaObject unityContext = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
  286. if (_androidPlugin != null)
  287. _androidPlugin.Call("SetSPAPContext", unityContext);
  288. #else
  289. //Unlock
  290. if (!licensecheck) {
  291. if (LicenseEmail == string.Empty)
  292. {
  293. //License
  294. StringBuilder owner = new StringBuilder(255);
  295. StringBuilder code = new StringBuilder(255);
  296. spapIsLicensed(owner, code, 255);
  297. LicenseEmail = owner.ToString();
  298. LicenseCode = code.ToString();
  299. if (LicenseEmail != "")
  300. Debug.Log("SerialPort Utility Pro Licensed E-Mail:" + LicenseEmail);
  301. else
  302. {
  303. LicenseEmail = "";
  304. Debug.Log("SerialPort Utility Pro is FREE VERSION.");
  305. }
  306. licensecheck = true;
  307. }
  308. else
  309. {
  310. Debug.Log("SerialPort Utility Pro Licensed E-Mail:" + LicenseEmail);
  311. licensecheck = true;
  312. }
  313. }
  314. #endif
  315. if (DebugConsoleMonitor) // && Debug.isDebugBuild
  316. {
  317. if (DebugConsoleObject == null)
  318. {
  319. //debug
  320. GameObject obj = Resources.Load<GameObject>("Prefabs/SPUPDebugConsole");
  321. DebugConsoleObject = Instantiate(obj);
  322. DebugConsoleObject.transform.SetParent(this.transform); //parent set
  323. }
  324. }
  325. //Auto Open
  326. if (IsAutoOpen)
  327. {
  328. Open();
  329. }
  330. }
  331. //End
  332. void OnDisable()
  333. {
  334. Close();
  335. }
  336. //Pause
  337. void OnApplicationPause(bool pauseStatus)
  338. {
  339. if (AutoRTSCTSHandshake)
  340. {
  341. if (pauseStatus) {
  342. RtsEnableSave = RtsGetStatus();
  343. RtsEnabled = false;
  344. }
  345. else
  346. RtsEnabled = RtsEnableSave;
  347. RtsEnable(RtsEnabled);
  348. }
  349. }
  350. public bool EnabledTransmission
  351. {
  352. set { this.EnableTrans = value; }
  353. get { return this.EnableTrans; }
  354. }
  355. /// <summary>
  356. /// Open Method
  357. /// </summary>
  358. public void Open()
  359. {
  360. if (IsOpened()) //Opened
  361. return;
  362. if (IsOpenProcessing())
  363. return;
  364. IsOpenProcess = true;
  365. StartCoroutine(OpenProcessing());
  366. }
  367. private System.Collections.IEnumerator OpenProcessing()
  368. {
  369. int SerialPortHandleSet = SPAPHANDLE_ERROR;
  370. IsErrFinished = false;
  371. //External File Configure
  372. if (ExternalConfig == true)
  373. ExternalConfigApply(ExternalConfigFileName);
  374. //method
  375. #if UNITY_ANDROID && !UNITY_EDITOR
  376. if(_androidPlugin != null)
  377. {
  378. AndroidJavaObject config = new AndroidJavaObject("com.wizapply.libspap.SpapConfig");
  379. config.Set<int>("BaudRate", BaudRate);
  380. config.Set<int>("Parity", (int)Parity);
  381. config.Set<int>("DataBit", (int)DataBit);
  382. config.Set<int>("StopBit", (int)StopBit);
  383. config.Set<int>("DiscardNull", (RecvDiscardNull == true) ? 1 : 0);
  384. config.Set<int>("IgnoreBreakSignal", (RecvIgnoreBreakSignal == true) ? 1 : 0);
  385. config.Set<int>("Skip", Skip);
  386. switch (OpenMethod) //Android
  387. {
  388. case SerialPortUtilityPro.OpenSystem.USB:
  389. SerialPortHandleSet = _androidPlugin.Call<int>("OpenUSB", VendorID, ProductID, SerialNumber_search_string, config);
  390. break;
  391. case SerialPortUtilityPro.OpenSystem.PCI:
  392. SerialPortHandleSet = _androidPlugin.Call<int>("OpenPCI", VendorID, config);
  393. break;
  394. case SerialPortUtilityPro.OpenSystem.BluetoothSSP:
  395. SerialPortHandleSet = _androidPlugin.Call<int>("OpenBtSPP", SerialNumber_search_string, config);
  396. break;
  397. case SerialPortUtilityPro.OpenSystem.NumberOrder:
  398. SerialPortHandleSet = _androidPlugin.Call<int>("Open", config);
  399. break;
  400. case SerialPortUtilityPro.OpenSystem.TCPSerialEmulatorClient:
  401. SerialPortHandleSet = _androidPlugin.Call<int>("OpenSerialEmulatorTCP", VendorID, ProductID);
  402. break;
  403. case SerialPortUtilityPro.OpenSystem.TCPSerialEmulatorServer:
  404. SerialPortHandleSet = _androidPlugin.Call<int>("OpenSerialEmulatorTCP", "", ProductID);
  405. break;
  406. default:
  407. SerialPortHandleSet = SPAPHANDLE_ERROR;
  408. break;
  409. }
  410. }
  411. #else
  412. //Start
  413. SpapConfig config;
  414. config.BaudRate = BaudRate;
  415. config.Parity = (int)Parity;
  416. config.DataBit = (int)DataBit;
  417. config.StopBit = (int)StopBit;
  418. config.DiscardNull = (RecvDiscardNull == true) ? 1 : 0;
  419. config.IgnoreBreakSignal = (RecvIgnoreBreakSignal == true) ? 1 : 0;
  420. config.Skip = Skip;
  421. switch (OpenMethod)
  422. {
  423. case SerialPortUtilityPro.OpenSystem.USB:
  424. SerialPortHandleSet = spapOpenUSB(VendorID_string, ProductID_string, SerialNumber_search_string, config);
  425. break;
  426. case SerialPortUtilityPro.OpenSystem.PCI:
  427. SerialPortHandleSet = spapOpenPCIe(VendorID_string, ProductID_string, SerialNumber_search_string, config);
  428. break;
  429. case SerialPortUtilityPro.OpenSystem.BluetoothSSP:
  430. SerialPortHandleSet = spapOpenBtVCOM(SerialNumber_search_string, config);
  431. break;
  432. case SerialPortUtilityPro.OpenSystem.NumberOrder:
  433. SerialPortHandleSet = spapOpen(config);
  434. break;
  435. case SerialPortUtilityPro.OpenSystem.TCPSerialEmulatorClient:
  436. SerialPortHandleSet = spapOpenSerialEmulatorTCP(VendorID_string, ProductID_string);
  437. break;
  438. case SerialPortUtilityPro.OpenSystem.TCPSerialEmulatorServer:
  439. SerialPortHandleSet = spapOpenSerialEmulatorTCP("", ProductID_string);
  440. break;
  441. }
  442. #endif
  443. RtsEnabled = RtsGetStatus(); //GetStatus
  444. DtrEnabled = DtrGetStatus();
  445. if (StartEnableDTR)
  446. DtrEnable(true);
  447. if (AutoRTSCTSHandshake)
  448. {
  449. RtsEnabled = true;
  450. RtsEnable(RtsEnabled);
  451. }
  452. RtsEnableSave = RtsEnabled;
  453. //Error
  454. if (SerialPortHandleSet == SPAPHANDLE_ERROR)
  455. {
  456. if (this != null)
  457. Debug.LogError("SerialPort UtilityPro attached to [" + this.name + "] is Open Error!");
  458. if (SystemEventObject != null)
  459. SystemEventObject.Invoke(this, "OPEN_ERROR");
  460. }
  461. #if UNITY_ANDROID && !UNITY_EDITOR
  462. //Andoid
  463. else if (SerialPortHandleSet == SPAPHANDLE_PERMISSION)
  464. { //hasParmission
  465. Invoke("Open", 3.0f); //Reconnect again in 3 seconds
  466. if(SystemEventObject != null)
  467. SystemEventObject.Invoke(this, "PERMISSION_ERROR");
  468. }
  469. #endif
  470. else
  471. {
  472. if (SystemEventObject != null)
  473. SystemEventObject.Invoke(this, "OPENED");
  474. }
  475. SerialDebugString = "";
  476. dataBuffer.Clear();
  477. SerialPortHandle = SerialPortHandleSet;
  478. IsOpenProcess = false;
  479. yield break;
  480. }
  481. //Invoke
  482. public void OpenInvoke(float time)
  483. {
  484. Invoke("Open", time); //Invoke Open
  485. }
  486. public void Close()
  487. {
  488. if (!IsOpened()) //Closed
  489. return;
  490. //Shutdown
  491. #if UNITY_ANDROID && !UNITY_EDITOR
  492. if (_androidPlugin != null) _androidPlugin.Call("Close", SerialPortHandle);
  493. #else
  494. spapClose(SerialPortHandle);
  495. #endif
  496. SerialPortHandle = SPAPHANDLE_ERROR;
  497. if (SystemEventObject != null)
  498. SystemEventObject.Invoke(this, "CLOSED");
  499. }
  500. // Update is called once per frame : ReadSystem
  501. void Update() //forUnity
  502. {
  503. if(UpdateProcessing == UpdateMethod.Update)
  504. ReadUpdate();
  505. }
  506. void FixedUpdate() //forUnity
  507. {
  508. if (UpdateProcessing == UpdateMethod.FixedUpdate)
  509. ReadUpdate();
  510. }
  511. // Update
  512. public void ReadUpdate()
  513. {
  514. if (!IsOpened()) //close
  515. return;
  516. if (IsOpenProcessing())
  517. return;
  518. int size = 0;
  519. #if UNITY_ANDROID && !UNITY_EDITOR
  520. if(_androidPlugin != null)
  521. size = _androidPlugin.Call<int>("ReadDataAvailable", SerialPortHandle);
  522. #else
  523. size = spapReadDataAvailable(SerialPortHandle);
  524. #endif
  525. if (size > 0)
  526. {
  527. byte[] dataArray = null;
  528. int iRet = 0;
  529. #if UNITY_ANDROID && !UNITY_EDITOR
  530. if(_androidPlugin != null) {
  531. iRet = (int)_androidPlugin.Call<long>("ReadData", SerialPortHandle, size);
  532. //dataArray = System.Array.ConvertAll(_androidPlugin.Get<sbyte[]>("m_byteData"), b => unchecked((byte)b));
  533. sbyte[] dataArray_signed = _androidPlugin.Get<sbyte[]>("m_byteData");
  534. dataArray = new byte[dataArray_signed.Length];
  535. System.Buffer.BlockCopy(dataArray_signed, 0, dataArray, 0, dataArray_signed.Length);
  536. }
  537. #else
  538. dataArray = new byte[size];
  539. iRet = spapReadData(SerialPortHandle, dataArray, size);
  540. #endif
  541. if (iRet <= 0 || dataArray == null) //Error
  542. return;
  543. //buffer
  544. dataBuffer.AddRange(dataArray.Take(iRet));
  545. //for debug Log
  546. string stringData = System.Text.Encoding.UTF8.GetString(dataArray, 0, iRet);
  547. if (EnableTrans)
  548. {
  549. switch (ReadProtocol)
  550. {
  551. case SerialPortUtilityPro.MethodSystem.SplitStringToArray: UpdateSplitToArray();
  552. break;
  553. case SerialPortUtilityPro.MethodSystem.FixedLengthDataToString: UpdateFixedCharacters(false);
  554. break;
  555. case SerialPortUtilityPro.MethodSystem.FixedLengthDataToBinary: UpdateFixedCharacters(true);
  556. break;
  557. case SerialPortUtilityPro.MethodSystem.SplitStringToDictionary: UpdateSplitToDictionary();
  558. break;
  559. case SerialPortUtilityPro.MethodSystem.JSONToClassObject: UpdateJsonObject();
  560. break;
  561. case SerialPortUtilityPro.MethodSystem.SplitStringToGameObject: UpdateArrayToClassMembers();
  562. break;
  563. case SerialPortUtilityPro.MethodSystem.LineFeedDataToString: UpdateLineFeed(false);
  564. break;
  565. case SerialPortUtilityPro.MethodSystem.LineFeedDataToBinary: UpdateLineFeed(true);
  566. break;
  567. case SerialPortUtilityPro.MethodSystem.BinaryStreaming: UpdateOnStreaming(true);
  568. break;
  569. case SerialPortUtilityPro.MethodSystem.ModbusASCII: UpdateModbus(false);
  570. break;
  571. case SerialPortUtilityPro.MethodSystem.ModbusRTU: UpdateModbus(true);
  572. break;
  573. default: UpdateOnStreaming(false);
  574. break;
  575. }
  576. SerialDebugAddString(" " + ControlCodeToView(stringData), false);
  577. }
  578. else
  579. {
  580. SerialDebugAddString(" <Is not valid>" + ControlCodeToView(stringData), false);
  581. }
  582. }
  583. else if (size == READDATA_ERROR_DISCONNECT)
  584. {
  585. //Disconnected
  586. Close();
  587. //Android
  588. #if UNITY_ANDROID && !UNITY_EDITOR
  589. if (!BluetoothSSPNoServerMode && _androidPlugin != null)
  590. {
  591. if (OpenMethod == SerialPortUtilityPro.OpenSystem.BluetoothSSP)
  592. {
  593. //Server Bluetooth
  594. SerialPortHandle = _androidPlugin.Call<int>("OpenBtSPP_Server");
  595. if (SerialPortHandle != SPAPHANDLE_ERROR)
  596. {
  597. if (SystemEventObject != null)
  598. SystemEventObject.Invoke(this, "BT_DISCONNECT_TO_SERVERMODE");
  599. return; //ServerMode
  600. }
  601. }
  602. }
  603. #endif
  604. IsErrFinished = true;
  605. Debug.LogError("SerialPort UtilityPro attached to [" + this.name + "] is Close!");
  606. if (SystemEventObject != null)
  607. SystemEventObject.Invoke(this, "DISCONNECT_ERROR");
  608. }
  609. else if (size == READDATA_ERROR_LICENSEEER)
  610. {
  611. //Disconnected
  612. Close();
  613. IsErrFinished = true;
  614. //License End
  615. Debug.LogError("SerialPortUtility Pro became transmission restriction (1MB) for FREE Version.\nYou can buy a License than this if you like it.\n* This limit is resettable by rebooting application. ");
  616. if (SystemEventObject != null)
  617. SystemEventObject.Invoke(this, "LICENSE_ERROR");
  618. }
  619. else if (size == 0)
  620. {
  621. if (ReadProtocol == SerialPortUtilityPro.MethodSystem.Streaming && EnableTrans)
  622. UpdateOnStreaming(false);
  623. if (ReadProtocol == SerialPortUtilityPro.MethodSystem.BinaryStreaming && EnableTrans)
  624. UpdateOnStreaming(true);
  625. }
  626. }
  627. public void SerialDebugAddString(string message, bool send_direction)
  628. {
  629. if(message.Length > 128) message = message.Remove(128); //max 128
  630. string dir = send_direction ? " (SEND)" : "";
  631. string debug = string.Format("[{0}{1}] {2}\n", System.DateTime.Now.ToString("MM/dd HH:mm:ss"), dir, message);
  632. SerialDebugString = SerialDebugString.Insert(0, debug);
  633. if (SerialDebugString.Split("\n".ToCharArray()).Length >= SerialDebugStringMAX)
  634. {
  635. SerialDebugString = SerialDebugString.Remove(SerialDebugString.LastIndexOf('\n'));
  636. }
  637. }
  638. //Converter
  639. private string ControlCodeToView(string inStr)
  640. {
  641. string outStr;
  642. string[] ctrlStr = { "NUL", "SOH", "STX", "ETX", "EOT", "ENQ", "ACK", "BEL",
  643. "BS", "HT", "LF", "VT", "NP", "CR", "SO", "SI"};
  644. outStr = System.Text.RegularExpressions.Regex.Replace(inStr, @"\p{Cc}", str =>
  645. {
  646. int offset = str.Value[0];
  647. if (ctrlStr.Length > offset)
  648. {
  649. return "<" + ctrlStr[offset] + ">";
  650. }
  651. else
  652. {
  653. return string.Format("<{0:X2}>", (byte)str.Value[0]);
  654. }
  655. });
  656. return outStr;
  657. }
  658. private string ViewToControlCode(string inStr)
  659. {
  660. //<NUL>, <CR>, <LF>, <STX>, <ETX>, <HT(TAB)>, <ACK>
  661. return inStr.Replace("<NUL>", "\0").Replace("<CR>", "\r").Replace("<LF>", "\n").Replace("<STX>", "\x02").Replace("<ETX>", "\x03").Replace("<HT>", "\t").Replace("<ACK>", "\x06");
  662. }
  663. /// <summary>
  664. /// Update Method
  665. /// </summary>
  666. private int OnStreamingCounter = 0;
  667. private int OnStreamingCounterLimit = 0;
  668. private const int OnStreamingCounterDetect = 10;
  669. private const int OnStreamingCounterLimitDetect = 120;
  670. private void UpdateOnStreaming(bool binaryMode)
  671. {
  672. if (dataBuffer.Count != 0)
  673. {
  674. OnStreamingCounter++;
  675. OnStreamingCounterLimit++;
  676. if ((OnStreamingCounter > OnStreamingCounterDetect) ||
  677. (OnStreamingCounterLimit > OnStreamingCounterLimitDetect))
  678. {
  679. if (binaryMode)
  680. ReadCompleteEventObject.Invoke(dataBuffer.ToArray());
  681. else {
  682. string buf = System.Text.Encoding.UTF8.GetString(dataBuffer.ToArray());
  683. ReadCompleteEventObject.Invoke(buf);
  684. }
  685. dataBuffer.Clear();
  686. OnStreamingCounter = 0;
  687. OnStreamingCounterLimit = 0;
  688. }
  689. }
  690. else
  691. {
  692. OnStreamingCounter = 0;
  693. }
  694. }
  695. private void UpdateSplitToArray()
  696. {
  697. //feedcode
  698. //spritcode change
  699. string fcode = ViewToControlCode(FeedCode);
  700. string scode = ViewToControlCode(SplitCode);
  701. int d;
  702. string dsbuf = System.Text.Encoding.UTF8.GetString(dataBuffer.ToArray());
  703. while ((d = dsbuf.IndexOf(fcode, 0)) >= 0)
  704. {
  705. List<string> _dataList = new List<string>();
  706. string str = dsbuf.Substring(0, d);
  707. string[] str2 = str.Split(scode.ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries);
  708. _dataList.Clear();
  709. foreach (string s in str2)
  710. _dataList.Add(s);
  711. dataBuffer.RemoveRange(0, d + fcode.Length); //delete
  712. if (ReadCompleteEventObject != null)
  713. ReadCompleteEventObject.Invoke(_dataList);
  714. dsbuf = System.Text.Encoding.UTF8.GetString(dataBuffer.ToArray());
  715. }
  716. }
  717. private int FixedCharactersCounter = 0;
  718. private int FixedCharactersCounterDetect = 120;
  719. private void UpdateFixedCharacters(bool binaryMode)
  720. {
  721. if (dataBuffer.Count != 0)
  722. {
  723. FixedCharactersCounter++;
  724. if (FixedCharactersCounter > FixedCharactersCounterDetect)
  725. {
  726. dataBuffer.Clear();
  727. FixedCharactersCounter = 0;
  728. }
  729. }
  730. while(dataBuffer.Count >= FixedFeedCount)
  731. {
  732. if (binaryMode)
  733. {
  734. byte[] dataByte = dataBuffer.GetRange(0, FixedFeedCount).ToArray();
  735. dataBuffer.RemoveRange(0, FixedFeedCount);
  736. FixedCharactersCounter = 0;
  737. if (ReadCompleteEventObject != null)
  738. ReadCompleteEventObject.Invoke((object)dataByte);
  739. }
  740. else
  741. {
  742. string str = System.Text.Encoding.UTF8.GetString(dataBuffer.ToArray());
  743. str = str.Substring(0, FixedFeedCount);
  744. dataBuffer.RemoveRange(0, FixedFeedCount);
  745. FixedCharactersCounter = 0;
  746. if (ReadCompleteEventObject != null)
  747. ReadCompleteEventObject.Invoke((object)str);
  748. }
  749. }
  750. }
  751. private void UpdateSplitToDictionary()
  752. {
  753. int d;
  754. string fcode = ViewToControlCode(FeedCode);
  755. string scode = ViewToControlCode(SplitCode);
  756. string dsbuf = System.Text.Encoding.UTF8.GetString(dataBuffer.ToArray());
  757. while ((d = dsbuf.IndexOf(fcode, 0)) >= 0)
  758. {
  759. Dictionary<string,string> _dataList = new Dictionary<string,string>();
  760. string str = dsbuf.Substring(0, d);
  761. string[] str2 = str.Split(scode.ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries);
  762. _dataList.Clear();
  763. for (int i = 0; i < str2.Length; ++i)
  764. {
  765. string[] strc = str2[i].Split(equalChar.ToCharArray(), System.StringSplitOptions.RemoveEmptyEntries);
  766. if (strc.Length == 2)
  767. {
  768. string key = strc[0];
  769. if (_dataList.ContainsKey(key))
  770. _dataList[key] = strc[1];
  771. else
  772. _dataList.Add(key, strc[1]);
  773. }
  774. }
  775. dataBuffer.RemoveRange(0, d + fcode.Length);
  776. if (ReadCompleteEventObject != null)
  777. ReadCompleteEventObject.Invoke((object)_dataList);
  778. dsbuf = System.Text.Encoding.UTF8.GetString(dataBuffer.ToArray());
  779. }
  780. }
  781. private void UpdateArrayToClassMembers()
  782. {
  783. int d;
  784. string fcode = ViewToControlCode(FeedCode);
  785. string scode = ViewToControlCode(SplitCode);
  786. string dsbuf = System.Text.Encoding.UTF8.GetString(dataBuffer.ToArray());
  787. while ((d = dsbuf.IndexOf(fcode, 0)) >= 0)
  788. {
  789. Dictionary<string, string> _dataList = new Dictionary<string, string>();
  790. string str = dsbuf.Substring(0, d);
  791. string[] str2 = str.Split(scode.ToCharArray(), System.StringSplitOptions.None);
  792. _dataList.Clear();
  793. for (int i = 0; i < str2.Length; ++i)
  794. {
  795. string[] strc = str2[i].Split(equalChar.ToCharArray(), System.StringSplitOptions.None);
  796. if (strc.Length == 2)
  797. {
  798. string key = strc[0];
  799. if (_dataList.ContainsKey(key))
  800. _dataList[key] = strc[1];
  801. else
  802. _dataList.Add(key, strc[1]);
  803. }
  804. }
  805. dataBuffer.RemoveRange(0, d + fcode.Length);
  806. //Set class
  807. if (ReadClassMembersObject != null)
  808. {
  809. foreach (MonoBehaviour listds in ReadClassMembersObject.GetComponents<MonoBehaviour>())
  810. {
  811. System.Type t = listds.GetType();
  812. foreach (System.Reflection.FieldInfo f in t.GetFields())
  813. {
  814. try
  815. {
  816. string key = string.Format("{0}.{1}", t.ToString(), f.Name);
  817. if (_dataList.ContainsKey(key))
  818. {
  819. f.SetValue(ReadClassMembersObject.GetComponent(t), System.Convert.ChangeType(_dataList[key],f.FieldType));
  820. }
  821. }
  822. catch (System.ArgumentNullException){}
  823. }
  824. }
  825. }
  826. dsbuf = System.Text.Encoding.UTF8.GetString(dataBuffer.ToArray());
  827. }
  828. }
  829. private void UpdateJsonObject()
  830. {
  831. string jsonFeedCode = "}";
  832. string jsonFeedCodeStart = "{";
  833. int d;
  834. string dsbuf = System.Text.Encoding.UTF8.GetString(dataBuffer.ToArray());
  835. while ((d = dsbuf.IndexOf(jsonFeedCode, 0)) >= 0)
  836. {
  837. int st = dsbuf.IndexOf(jsonFeedCodeStart, 0);
  838. string dataStr = dsbuf.Substring(st, d - st + jsonFeedCode.Length);
  839. dataBuffer.RemoveRange(0, d + jsonFeedCode.Length);
  840. if (ReadCompleteEventObject != null)
  841. {
  842. try {
  843. if (ReadCompleteEventObjectType != "")
  844. ReadCompleteEventObject.Invoke(JsonUtility.FromJson(dataStr, System.Type.GetType(ReadCompleteEventObjectType)));
  845. } catch(System.ArgumentNullException){
  846. Debug.Log("Error Object Type");
  847. }
  848. }
  849. dsbuf = System.Text.Encoding.UTF8.GetString(dataBuffer.ToArray());
  850. }
  851. }
  852. private void UpdateLineFeed(bool BinaryMode)
  853. {
  854. int d;
  855. string fcode = ViewToControlCode(FeedCode);
  856. string dsbuf = System.Text.Encoding.UTF8.GetString(dataBuffer.ToArray());
  857. while ((d = dsbuf.IndexOf(fcode, 0)) >= 0)
  858. {
  859. if (BinaryMode)
  860. {
  861. byte[] dataByte = dataBuffer.GetRange(0, d).ToArray();
  862. dataBuffer.RemoveRange(0, d + fcode.Length);
  863. if (ReadCompleteEventObject != null)
  864. ReadCompleteEventObject.Invoke((object)dataByte);
  865. }
  866. else
  867. {
  868. string dataStr = dsbuf.Substring(0, d);
  869. dataBuffer.RemoveRange(0, d + fcode.Length);
  870. if (ReadCompleteEventObject != null)
  871. ReadCompleteEventObject.Invoke((object)dataStr);
  872. }
  873. dsbuf = System.Text.Encoding.UTF8.GetString(dataBuffer.ToArray());
  874. }
  875. }
  876. private void UpdateModbus(bool RtuMode)
  877. {
  878. int d;
  879. if (RtuMode)
  880. {
  881. //RTU beta
  882. SPUPMudbusData dataModbus = null;
  883. int datasize = dataBuffer.Count;
  884. byte[] dataByte = dataBuffer.GetRange(0, datasize).ToArray();
  885. dataBuffer.RemoveRange(0, datasize);
  886. int bytelen = dataByte.Length - 2;
  887. byte[] crc16 = GetCRC16(dataByte, 0, bytelen);
  888. if (crc16[0] == dataByte[dataByte.Length - 2] && crc16[1] == dataByte[dataByte.Length - 1])
  889. {
  890. byte[] sendData = new byte[bytelen - 2]; //Address, Function, CRC16 = 4byte
  891. System.Array.Copy(dataByte, 2, sendData, 0, bytelen - 2); // address & function = 2byte
  892. dataModbus = new SPUPMudbusData(dataByte[0], dataByte[1], sendData);
  893. }
  894. if (dataModbus != null)
  895. {
  896. if (ReadCompleteEventObject != null)
  897. ReadCompleteEventObject.Invoke((object)dataModbus);
  898. }
  899. }
  900. else
  901. {
  902. //ASCII
  903. string fcode = "\r\n"; //feedcode = <CR><LF>
  904. string dsbuf = System.Text.Encoding.UTF8.GetString(dataBuffer.ToArray());
  905. while ((d = dsbuf.IndexOf(fcode, 0)) >= 0)
  906. {
  907. int f_colon = dsbuf.IndexOf(":", 0) + 1;
  908. SPUPMudbusData dataModbus = null;
  909. if (f_colon > 0 && f_colon <= d)
  910. {
  911. string dataStr = dsbuf.Substring(f_colon, d - f_colon);
  912. byte[] dataBin = StringToBytes(dataStr);
  913. if(dataBin.Length >= 3) {
  914. //LRC
  915. byte lrc = GetLRC(dataBin, 0, dataBin.Length-1);
  916. if (lrc == dataBin[dataBin.Length - 1])
  917. {
  918. //OK
  919. int bytelen = dataBin.Length - 3;
  920. byte[] sendData = new byte[bytelen]; //Address, Function, LRC = 3byte
  921. System.Array.Copy(dataBin, 2, sendData, 0, bytelen);
  922. dataModbus = new SPUPMudbusData(dataBin[0], dataBin[1], sendData);
  923. }
  924. }
  925. }
  926. dataBuffer.RemoveRange(0, d + fcode.Length);
  927. if(dataModbus != null) {
  928. if (ReadCompleteEventObject != null)
  929. ReadCompleteEventObject.Invoke((object)dataModbus);
  930. }
  931. dsbuf = System.Text.Encoding.UTF8.GetString(dataBuffer.ToArray());
  932. }
  933. }
  934. }
  935. private static byte GetLRC(byte[] message, int start, int end)
  936. {
  937. byte LRC = 0;
  938. for (int i = start; i < end; i++)
  939. LRC -= message[i];
  940. return LRC;
  941. }
  942. private static byte[] GetCRC16(byte[] message, int start, int end)
  943. {
  944. ushort CRCFull = 0xFFFF;
  945. byte CRCHigh = 0xFF, CRCLow = 0xFF;
  946. byte CRCLSB;
  947. byte[] crc16 = new byte[2];
  948. for (int i = start; i < end; i++)
  949. {
  950. CRCFull = (ushort)(CRCFull ^ message[i]);
  951. for (int j = 0; j < 8; j++)
  952. {
  953. CRCLSB = (byte)(CRCFull & 0x0001);
  954. CRCFull = (ushort)(CRCFull >> 1);
  955. if (CRCLSB > 0)
  956. CRCFull = (ushort)(CRCFull ^ 0xA001);
  957. }
  958. }
  959. crc16[1] = CRCHigh = (byte)((CRCFull >> 8) & 0xFF);
  960. crc16[0] = CRCLow = (byte)(CRCFull & 0xFF);
  961. return crc16;
  962. }
  963. private byte[] StringToBytes(string str)
  964. {
  965. var bs = new List<byte>();
  966. for (int i = 0; i < str.Length / 2; i++)
  967. bs.Add(System.Convert.ToByte(str.Substring(i * 2, 2), 16));
  968. return bs.ToArray();
  969. }
  970. //Write
  971. public bool Write(string writeString)
  972. {
  973. if (AutoRTSCTSHandshake)
  974. {
  975. if (!CtsHolding()) return false;
  976. }
  977. if (!EnableTrans)
  978. return false;
  979. Write(System.Text.Encoding.UTF8.GetBytes(writeString));
  980. return true;
  981. }
  982. public bool Write(byte[] writeData)
  983. {
  984. if (AutoRTSCTSHandshake)
  985. {
  986. if (!CtsHolding()) return false;
  987. }
  988. if (!EnableTrans)
  989. return false;
  990. #if UNITY_ANDROID && !UNITY_EDITOR
  991. if(_androidPlugin != null)
  992. _androidPlugin.Call("WriteBuffer", SerialPortHandle, writeData, writeData.Length);
  993. #else
  994. GCHandle wd = GCHandle.Alloc(writeData, GCHandleType.Pinned);
  995. spapWrite(SerialPortHandle, wd.AddrOfPinnedObject(), writeData.Length);
  996. wd.Free();
  997. #endif
  998. SerialDebugAddString(ControlCodeToView(System.Text.Encoding.UTF8.GetString(writeData)),true);
  999. return true;
  1000. }
  1001. public bool Write(byte writeOneData)
  1002. {
  1003. byte[] writeData = new byte[1] { writeOneData };
  1004. return Write(writeData);
  1005. }
  1006. public bool WriteJSON(object jsonObject)
  1007. {
  1008. if (jsonObject == null)
  1009. return false;
  1010. try
  1011. {
  1012. return Write(JsonUtility.ToJson(jsonObject));
  1013. }
  1014. catch(System.ArgumentException)
  1015. {
  1016. Debug.LogError("The specified object is not convertible for JSON format.");
  1017. return false;
  1018. }
  1019. }
  1020. public bool Write(string writeString, string feedCode)
  1021. {
  1022. string fcode = ViewToControlCode(feedCode);
  1023. return Write(writeString + fcode);
  1024. }
  1025. public bool WriteCRLF(string writeString)
  1026. {
  1027. return Write(writeString + "\r\n");
  1028. }
  1029. public bool WriteCR(string writeString)
  1030. {
  1031. return Write(writeString + "\r");
  1032. }
  1033. public bool WriteLF(string writeString)
  1034. {
  1035. return Write(writeString + "\n");
  1036. }
  1037. public bool Write(List<string> writeString, string splitCode, string feedCode)
  1038. {
  1039. string resString = "";
  1040. string fcode = ViewToControlCode(feedCode);
  1041. foreach (string s in writeString) {
  1042. resString += s + splitCode;
  1043. }
  1044. return Write(resString + fcode);
  1045. }
  1046. public bool Write(Dictionary<string, string> writeString, string splitCode, string feedCode)
  1047. {
  1048. string resString = "";
  1049. List<string> keyList = new List<string>(writeString.Keys);
  1050. string fcode = ViewToControlCode(feedCode);
  1051. foreach (string key in keyList)
  1052. resString += key + equalChar + writeString[key] + splitCode;
  1053. return Write(writeString + fcode);
  1054. }
  1055. public bool Write(GameObject gameObject_string, string splitCode, string feedCode)
  1056. {
  1057. if (gameObject_string != null)
  1058. {
  1059. List<string> sendData = new List<string>();
  1060. foreach (MonoBehaviour listds in ReadClassMembersObject.GetComponents<MonoBehaviour>())
  1061. {
  1062. System.Type t = listds.GetType();
  1063. foreach (System.Reflection.FieldInfo f in t.GetFields())
  1064. {
  1065. if (f.FieldType == typeof(string))
  1066. {
  1067. string key = string.Format("{0}.{1}", t.ToString(), f.Name);
  1068. string data = f.GetValue(gameObject_string.GetComponent(t)) as string;
  1069. sendData.Add(key + equalChar + data);
  1070. }
  1071. }
  1072. }
  1073. //Send
  1074. if (Write(sendData, splitCode, feedCode))
  1075. return false;
  1076. }
  1077. return true;
  1078. }
  1079. public bool Write(SPUPMudbusData mudbus_data, bool rtuMode = false)
  1080. {
  1081. if (rtuMode)
  1082. {
  1083. //beta
  1084. int byteindex = 0;
  1085. int dataframe_addition = 4;
  1086. byte[] dataframe = new byte[mudbus_data.Data.Length + dataframe_addition];
  1087. dataframe[byteindex] = mudbus_data.Address; byteindex++;
  1088. dataframe[byteindex] = mudbus_data.Function; byteindex++;
  1089. System.Array.Copy(mudbus_data.Data,0, dataframe, byteindex, mudbus_data.Data.Length);
  1090. byteindex += mudbus_data.Data.Length;
  1091. byte[] crc16 = GetCRC16(dataframe, 0, dataframe.Length-2); //address & function = -2byte
  1092. dataframe[byteindex] = crc16[0]; byteindex++;
  1093. dataframe[byteindex] = crc16[1]; byteindex++;
  1094. System.Threading.Thread.Sleep(6); //No communication time: >9600
  1095. return Write(dataframe);
  1096. }
  1097. else
  1098. {
  1099. string sendDataString = "";
  1100. sendDataString += string.Format("{0:X2}", mudbus_data.Address);
  1101. sendDataString += string.Format("{0:X2}", mudbus_data.Function);
  1102. for (int i = 0; i < mudbus_data.Data.Length; i++)
  1103. sendDataString += string.Format("{0:X2}", mudbus_data.Data[i]);
  1104. byte[] ba = StringToBytes(sendDataString);
  1105. byte lrc = GetLRC(ba, 0, ba.Length);
  1106. sendDataString += string.Format("{0:X2}", lrc);
  1107. return Write(":" + sendDataString, "<CR><LF>");
  1108. }
  1109. }
  1110. //Proparty
  1111. public bool IsOpened()
  1112. {
  1113. return SerialPortHandle >= 0;
  1114. }
  1115. public bool IsErrorFinished()
  1116. {
  1117. return IsErrFinished;
  1118. }
  1119. public bool IsOpenProcessing()
  1120. {
  1121. return IsOpenProcess;
  1122. }
  1123. public void RtsEnable(bool enable)
  1124. {
  1125. #if UNITY_ANDROID && !UNITY_EDITOR
  1126. if(_androidPlugin != null)
  1127. _androidPlugin.Call("SetRTS", SerialPortHandle, enable);
  1128. #else
  1129. spapSetRTS(SerialPortHandle, enable);
  1130. #endif
  1131. RtsEnabled = enable;
  1132. }
  1133. public void DtrEnable(bool enable)
  1134. {
  1135. #if UNITY_ANDROID && !UNITY_EDITOR
  1136. if(_androidPlugin != null)
  1137. _androidPlugin.Call("SetDTR", SerialPortHandle, enable);
  1138. #else
  1139. spapSetDTR(SerialPortHandle, enable);
  1140. #endif
  1141. DtrEnabled = enable;
  1142. }
  1143. public bool RtsGetStatus()
  1144. {
  1145. #if UNITY_ANDROID && !UNITY_EDITOR
  1146. if(_androidPlugin != null)
  1147. return _androidPlugin.Call<bool>("GetRTS", SerialPortHandle);
  1148. return false;
  1149. #else
  1150. return spapGetRTS(SerialPortHandle);
  1151. #endif
  1152. }
  1153. public bool DtrGetStatus()
  1154. {
  1155. #if UNITY_ANDROID && !UNITY_EDITOR
  1156. if(_androidPlugin != null)
  1157. return _androidPlugin.Call<bool>("GetDTR", SerialPortHandle);
  1158. return false;
  1159. #else
  1160. return spapGetDTR(SerialPortHandle);
  1161. #endif
  1162. }
  1163. public bool CtsHolding()
  1164. {
  1165. #if UNITY_ANDROID && !UNITY_EDITOR
  1166. if(_androidPlugin != null)
  1167. return _androidPlugin.Call<bool>("GetCTS", SerialPortHandle);
  1168. return false;
  1169. #else
  1170. return spapGetCTS(SerialPortHandle);
  1171. #endif
  1172. }
  1173. public bool DsrHolding()
  1174. {
  1175. #if UNITY_ANDROID && !UNITY_EDITOR
  1176. if(_androidPlugin != null)
  1177. return _androidPlugin.Call<bool>("GetDSR", SerialPortHandle);
  1178. return false;
  1179. #else
  1180. return spapGetDSR(SerialPortHandle);
  1181. #endif
  1182. }
  1183. public bool IsConnected()
  1184. {
  1185. return DsrHolding();
  1186. }
  1187. public void SetBreakSignal(bool enable)
  1188. {
  1189. #if UNITY_ANDROID && !UNITY_EDITOR
  1190. if(_androidPlugin != null)
  1191. _androidPlugin.Call("BreakSignal", SerialPortHandle, enable);
  1192. #else
  1193. spapBreakSignal(SerialPortHandle, enable);
  1194. #endif
  1195. }
  1196. private void ExternalConfigApply(string filePath)
  1197. {
  1198. //The variable of this object is read and reflected in an external file before Open().
  1199. if (filePath == string.Empty)
  1200. return;
  1201. string fileSetPath = "";
  1202. switch (this.ExternalConfigPath)
  1203. {
  1204. case SourcePath.RelativeToDataFolder: fileSetPath += Application.dataPath;
  1205. break;
  1206. case SourcePath.RelativeToPeristentDataFolder: fileSetPath += Application.persistentDataPath;
  1207. break;
  1208. case SourcePath.RelativeToStreamingAssetsFolder: fileSetPath += Application.streamingAssetsPath;
  1209. break;
  1210. case SourcePath.AbsolutePath:
  1211. default:
  1212. break;
  1213. }
  1214. fileSetPath += "/" + filePath;
  1215. if (!System.IO.File.Exists(fileSetPath))
  1216. return;
  1217. Debug.Log(string.Format("The set of the external file was applied. : {0}",fileSetPath));
  1218. System.IO.StreamReader sr = new System.IO.StreamReader(fileSetPath, Encoding.UTF8);
  1219. while (sr.Peek() != -1)
  1220. {
  1221. string ld = sr.ReadLine();
  1222. ld = ld.Replace("\t", "").Replace(" ", ""); //tab & space delete
  1223. ld = ld.Split('#')[0]; //commnet
  1224. if (ld.Length <= 0)
  1225. continue; //igune
  1226. string[] str = ld.Split("=".ToCharArray(), System.StringSplitOptions.None);
  1227. if (str.Length != 2)
  1228. continue; //igune
  1229. System.Type t = this.GetType();
  1230. foreach (System.Reflection.PropertyInfo p in t.GetProperties())
  1231. {
  1232. if (p.Name == str[0])
  1233. {
  1234. try
  1235. {
  1236. if(p.PropertyType == typeof(string))
  1237. {
  1238. p.SetValue(this.GetComponent(t), str[1], null);
  1239. Debug.Log(string.Format("ExternalConfig Apply! {0} = {1}", str[0], str[1]));
  1240. }
  1241. }
  1242. catch (System.ArgumentException)
  1243. {
  1244. Debug.LogError(string.Format("ExternalConfig Error! {0}", str[0]));
  1245. }
  1246. }
  1247. }
  1248. foreach (System.Reflection.FieldInfo f in t.GetFields())
  1249. {
  1250. if (f.Name == str[0])
  1251. {
  1252. try
  1253. {
  1254. if (f.FieldType == typeof(string))
  1255. {
  1256. f.SetValue(this.GetComponent(t), str[1]);
  1257. Debug.Log(string.Format("ExternalConfig Apply!{0} = {1}", str[0], str[1]));
  1258. }
  1259. else if (f.FieldType == typeof(float))
  1260. {
  1261. f.SetValue(this.GetComponent(t), float.Parse(str[1]));
  1262. Debug.Log(string.Format("ExternalConfig Apply!{0} = {1}", str[0], str[1]));
  1263. }
  1264. else if (f.FieldType == typeof(bool))
  1265. {
  1266. f.SetValue(this.GetComponent(t), bool.Parse(str[1]));
  1267. Debug.Log(string.Format("ExternalConfig Apply!{0} = {1}", str[0], str[1]));
  1268. }
  1269. else if (f.FieldType == typeof(int))
  1270. {
  1271. f.SetValue(this.GetComponent(t), int.Parse(str[1]));
  1272. Debug.Log(string.Format("ExternalConfig Apply!{0} = {1}", str[0], str[1]));
  1273. }
  1274. else if (f.FieldType == typeof(ParityEnum))
  1275. {
  1276. ParityEnum ve = (ParityEnum)int.Parse(str[1]);
  1277. f.SetValue(this.GetComponent(t), ve);
  1278. Debug.Log(string.Format("ExternalConfig Apply!{0} = {1}", str[0], str[1]));
  1279. }
  1280. else if (f.FieldType == typeof(StopBitEnum))
  1281. {
  1282. StopBitEnum ve = (StopBitEnum)int.Parse(str[1]);
  1283. f.SetValue(this.GetComponent(t), ve);
  1284. Debug.Log(string.Format("ExternalConfig Apply!{0} = {1}", str[0], str[1]));
  1285. }
  1286. else if (f.FieldType == typeof(DataBitEnum))
  1287. {
  1288. DataBitEnum ve = (DataBitEnum)int.Parse(str[1]);
  1289. f.SetValue(this.GetComponent(t), ve);
  1290. Debug.Log(string.Format("ExternalConfig Apply!{0} = {1}", str[0], str[1]));
  1291. }
  1292. }
  1293. catch (System.ArgumentException)
  1294. {
  1295. Debug.LogError(string.Format("ExternalConfig Error! {0}", str[0]));
  1296. }
  1297. }
  1298. }
  1299. }
  1300. sr.Close();
  1301. }
  1302. //DeviceList
  1303. public static DeviceInfo[] GetConnectedDeviceList(OpenSystem device_format)
  1304. {
  1305. DeviceInfo[] deviceInfo = null;
  1306. #if UNITY_ANDROID && !UNITY_EDITOR
  1307. if (device_format == OpenSystem.USB) {
  1308. AndroidJavaClass spapLibClass = new AndroidJavaClass("com.wizapply.libspap.spap");
  1309. // Get Context(Activity) Object
  1310. AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
  1311. AndroidJavaObject unityContext = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
  1312. if (spapLibClass != null) {
  1313. string usbList = spapLibClass.CallStatic<string>("GetUSBConnection", unityContext);
  1314. if (usbList.Length == 0) //isEmpty
  1315. return deviceInfo;
  1316. string[] deviceKind = usbList.Split(';');
  1317. int dKlen = deviceKind.Length - 1;
  1318. deviceInfo = new DeviceInfo[dKlen];
  1319. for(int i=0; i < dKlen; ++i)
  1320. {
  1321. string[] datu = deviceKind[i].Split(',');
  1322. deviceInfo[i] = new DeviceInfo();
  1323. deviceInfo[i].Vendor = datu[0]; //VID
  1324. deviceInfo[i].Product = datu[1]; //PID
  1325. deviceInfo[i].SerialNumber = datu[2]; //SerialNumber
  1326. deviceInfo[i].PortName = "";
  1327. }
  1328. }
  1329. }
  1330. else if (device_format == OpenSystem.PCI)
  1331. {
  1332. AndroidJavaClass spapLibClass = new AndroidJavaClass("com.wizapply.libspap.spap");
  1333. // Get Context(Activity) Object
  1334. AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
  1335. AndroidJavaObject unityContext = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
  1336. if (spapLibClass != null)
  1337. {
  1338. string usbList = spapLibClass.CallStatic<string>("GetPCIConnection", unityContext);
  1339. if (usbList.Length == 0) //isEmpty
  1340. return deviceInfo;
  1341. string[] deviceKind = usbList.Split(';');
  1342. int dKlen = deviceKind.Length - 1;
  1343. deviceInfo = new DeviceInfo[dKlen];
  1344. for (int i = 0; i < dKlen; ++i)
  1345. {
  1346. string[] datu = deviceKind[i].Split(',');
  1347. deviceInfo[i] = new DeviceInfo();
  1348. deviceInfo[i].Vendor = datu[0]; //VID
  1349. deviceInfo[i].Product = ""; //PID
  1350. deviceInfo[i].SerialNumber = ""; //SerialNumber
  1351. deviceInfo[i].PortName = datu[0];
  1352. }
  1353. }
  1354. }
  1355. else if (device_format == OpenSystem.BluetoothSSP)
  1356. {
  1357. AndroidJavaClass androidPlugin = new AndroidJavaClass("com.wizapply.libspap.spap");
  1358. // Get Context(Activity) Object
  1359. AndroidJavaClass unityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
  1360. AndroidJavaObject unityContext = unityPlayer.GetStatic<AndroidJavaObject>("currentActivity");
  1361. if (androidPlugin != null) {
  1362. string usbList = androidPlugin.CallStatic<string>("GetBluetoothConnection", unityContext);
  1363. if (usbList.Length == 0) //isEmpty
  1364. return deviceInfo;
  1365. string[] deviceKind = usbList.Split(';');
  1366. int dKlen = deviceKind.Length - 1;
  1367. deviceInfo = new DeviceInfo[dKlen];
  1368. for (int i = 0; i < dKlen; ++i)
  1369. {
  1370. string[] datu = deviceKind[i].Split(',');
  1371. deviceInfo[i] = new DeviceInfo();
  1372. deviceInfo[i].SerialNumber = datu[0]; //SerialNumber
  1373. }
  1374. }
  1375. }
  1376. else
  1377. {
  1378. Debug.LogError("GetConnectedDeviceList is NOT SUPPORTED!");
  1379. }
  1380. #else
  1381. int deviceNum = spapDeviceListAvailable();
  1382. System.Text.StringBuilder[] deviceString = new System.Text.StringBuilder[deviceNum];
  1383. int[] deviceKind = new int[deviceNum];
  1384. for (int i = 0; i < deviceNum; i++)
  1385. {
  1386. deviceString[i] = new System.Text.StringBuilder(1024);
  1387. deviceKind[i] = spapDeviceList(i, deviceString[i], 1024);
  1388. }
  1389. //length
  1390. int deviceInfoNum = 0;
  1391. for (int i = 0; i < deviceNum; i++)
  1392. {
  1393. int openMethod = (int)device_format;
  1394. string[] datu = deviceString[i].ToString().Split(',');
  1395. if (openMethod == deviceKind[i])
  1396. {
  1397. if (datu[0] == "null")
  1398. continue;
  1399. deviceInfoNum++;
  1400. }
  1401. }
  1402. int device_i = 0;
  1403. deviceInfo = new DeviceInfo[deviceInfoNum];
  1404. for (int i = 0; i < deviceNum; i++)
  1405. {
  1406. int openMethod = (int)device_format;
  1407. string[] datu = deviceString[i].ToString().Split(',');
  1408. if (openMethod == deviceKind[i])
  1409. {
  1410. if (datu[0] == "null")
  1411. continue;
  1412. switch (device_format)
  1413. {
  1414. case SerialPortUtilityPro.OpenSystem.USB:
  1415. deviceInfo[device_i] = new DeviceInfo();
  1416. deviceInfo[device_i].Vendor = datu[0];
  1417. deviceInfo[device_i].Product = datu[1];
  1418. deviceInfo[device_i].SerialNumber = datu[2];
  1419. deviceInfo[device_i].PortName = datu[3];
  1420. break;
  1421. case SerialPortUtilityPro.OpenSystem.PCI:
  1422. deviceInfo[device_i] = new DeviceInfo();
  1423. deviceInfo[device_i].Vendor = datu[0];
  1424. deviceInfo[device_i].Product = datu[1];
  1425. deviceInfo[device_i].SerialNumber = "";
  1426. deviceInfo[device_i].PortName = datu[2];
  1427. break;
  1428. case SerialPortUtilityPro.OpenSystem.BluetoothSSP:
  1429. deviceInfo[device_i] = new DeviceInfo();
  1430. deviceInfo[device_i].Vendor = "";
  1431. deviceInfo[device_i].Product = "";
  1432. deviceInfo[device_i].SerialNumber = datu[0];
  1433. deviceInfo[device_i].PortName = datu[0];
  1434. break;
  1435. }
  1436. device_i++;
  1437. }
  1438. }
  1439. #endif
  1440. return deviceInfo;
  1441. }
  1442. }
  1443. }