PageRenderTime 295ms CodeModel.GetById 30ms RepoModel.GetById 1ms app.codeStats 1ms

/Library/PRIMITIVES/TspInstrument.vb

https://bitbucket.org/davidhary/isr.tsp.vb.3.x
Visual Basic | 5519 lines | 3131 code | 886 blank | 1502 comment | 22 complexity | 2818617540a2164c5a6c36c94204e5ea MD5 | raw file
  1. Imports isr.Core.StringExtensions
  2. ''' <summary>
  3. ''' Defines the I/O driver for accessing the master node of a TSP Linked system.
  4. ''' </summary>
  5. ''' <remarks>
  6. ''' </remarks>
  7. ''' <license>
  8. ''' (c) 2010 Integrated Scientific Resources, Inc.
  9. ''' Licensed under the Apache License Version 2.0.
  10. ''' Unless required by applicable law or agreed to in writing, this software is provided
  11. ''' "AS IS", WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. ''' </license>
  13. ''' <history date="02/21/2009" by="David Hary" revision="3.0.3339.x">
  14. ''' Created
  15. ''' </history>
  16. Public Class TspInstrument
  17. Inherits isr.Visa.Ieee4882.Instrument
  18. Implements ITspInstrument
  19. #Region " CONSTRUCTORS and DESTRUCTORS "
  20. ''' <summary>Constructs this class.</summary>
  21. ''' <param name="resourceTitle">Specifies the instrument name.</param>
  22. Public Sub New(ByVal resourceTitle As String)
  23. MyBase.New(resourceTitle)
  24. Me._statusLatency = 1
  25. Me._statusRepeatCount = 3
  26. ' Creating TSP status manager..."
  27. ' My.MyLibrary.TspStatus = New isr.Tsp.TspStatus(Me)
  28. ' default to 8 nodes at this point
  29. Me._maximumNodeCount = 8
  30. Me._usingTspLink = True
  31. Me._systemInitTimeout = 30000
  32. Me._nilifyTimeout = 10000
  33. Me._deleteTimeout = 10000
  34. Me._saveTimeout = 10000
  35. MyBase.ErrorAvailableBits = Visa.Ieee4882.ServiceRequests.ErrorAvailable
  36. MyBase.MessageAvailableBits = Visa.Ieee4882.ServiceRequests.MessageAvailable
  37. MyBase.IsCheckBufferOnReceive = True
  38. MyBase.IsCheckBufferOnSend = True
  39. MyBase.IsCheckOpcAfterSend = False
  40. MyBase.IsDelegateErrorHandling = False
  41. Me.NewLegacyScripts()
  42. Me.NewScripts()
  43. ' set default commands and query commands.
  44. MyBase.ErrorQueueQueryCommand = TspSyntax.ErrorQueueQueryCommand(TspSyntax.GlobalNode)
  45. MyBase.ErrorQueueCountQueryCommand = TspSyntax.ErrorQueueCountQueryCommand(TspSyntax.GlobalNode)
  46. MyBase.ClearErrorQueueCommand = TspSyntax.ClearErrorQueueCommand(TspSyntax.GlobalNode)
  47. ' include the error clear command for compatibility with 2400 instruments.
  48. MyBase.ClearExecutionStateCommand = TspSyntax.ClearExecutionStateCommand(TspSyntax.GlobalNode)
  49. ' *IDN? *WAI
  50. MyBase.IdentifyQueryCommand = isr.Visa.Ieee4882.Syntax.IdentifyQueryCommand & " " & isr.Visa.Ieee4882.Syntax.WaitCommand
  51. ' MyBase.IdentifyQueryCommand = TspSyntax.IdentifyQueryCommand(TspSyntax.LocalNode)
  52. 'MyBase.OperationCompletedCommand = isr.Visa.Ieee4882.Syntax.OperationCompletedCommand ' "*OPC"
  53. MyBase.OperationCompletedCommand = TspSyntax.OperationCompletedCommand ' "opc()"
  54. 'MyBase.OperationCompletedQueryCommand = isr.Visa.Ieee4882.Syntax.OperationCompletedQueryCommand ' "*OPC?"
  55. MyBase.OperationCompletedQueryCommand = TspSyntax.OperationCompletedQueryCommand ' "waitcomplete() print(1)"
  56. MyBase.OperationEventEnableCommand = TspSyntax.OperationEventEnableCommand(TspSyntax.GlobalNode)
  57. MyBase.OperationEventEnableQueryCommand = TspSyntax.OperationEventEnableQueryCommand(TspSyntax.GlobalNode)
  58. MyBase.OperationEventStatusQueryCommand = TspSyntax.OperationEventStatusQueryCommand(TspSyntax.GlobalNode)
  59. ' Use reset() to reset all devices on the TSP link.
  60. MyBase.ResetKnownStateCommand = TspSyntax.ResetKnownStateCommand(TspSyntax.GlobalNode)
  61. MyBase.ServiceRequestEnableCommand = TspSyntax.ServiceRequestEnableCommand(TspSyntax.GlobalNode)
  62. MyBase.ServiceRequestEnableQueryCommand = TspSyntax.ServiceRequestEnableQueryCommand(TspSyntax.LocalNode)
  63. MyBase.ServiceRequestStatusQueryCommand = TspSyntax.ServiceRequestStatusQueryCommand(TspSyntax.LocalNode)
  64. MyBase.StandardEventEnableCommand = TspSyntax.StandardEventEnableCommand(TspSyntax.GlobalNode)
  65. MyBase.StandardEventEnableQueryCommand = TspSyntax.StandardEventEnableQueryCommand(TspSyntax.GlobalNode)
  66. MyBase.StandardEventStatusQueryCommand = TspSyntax.StandardEventStatusQueryCommand(TspSyntax.GlobalNode)
  67. MyBase.WaitCommand = isr.Visa.Ieee4882.Syntax.WaitCommand ' "*WAI"
  68. ' TSP instrument Ready to Connect.
  69. End Sub
  70. ''' <summary>Cleans up unmanaged or managed and unmanaged resources.</summary>
  71. ''' <param name="disposing">True if this method releases both managed and unmanaged
  72. ''' resources; False if this method releases only unmanaged resources.</param>
  73. ''' <remarks>Executes in two distinct scenarios as determined by
  74. ''' its disposing parameter. If True, the method has been called directly or
  75. ''' indirectly by a user's code--managed and unmanaged resources can be disposed.
  76. ''' If disposing equals False, the method has been called by the
  77. ''' runtime from inside the finalizer and you should not reference
  78. ''' other objects--only unmanaged resources can be disposed.</remarks>
  79. <System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2215:Dispose methods should call base class dispose")>
  80. Protected Overrides Sub Dispose(ByVal disposing As Boolean)
  81. Try
  82. If Not MyBase.IsDisposed Then
  83. If disposing Then
  84. ' Free managed resources when explicitly called
  85. Me._legacyScripts.Dispose()
  86. Me._scripts.Dispose()
  87. If MyBase.IsConnected Then
  88. MyBase.Disconnect()
  89. End If
  90. End If
  91. ' Free shared unmanaged resources
  92. End If
  93. Finally
  94. ' invoke the dispose method on the base class.
  95. MyBase.Dispose(disposing)
  96. End Try
  97. End Sub
  98. #End Region
  99. #Region " SINGLETON "
  100. ''' <summary>
  101. ''' The locking object to enforce thread safety when creating the singleton instance.
  102. ''' </summary>
  103. Private Shared ReadOnly syncLocker As New Object
  104. ''' <summary>
  105. ''' Disposes of the default instance.
  106. ''' </summary>
  107. Public Shared Sub DisposeDefault()
  108. If TspInstrument.Instantiated Then
  109. SyncLock TspInstrument.syncLocker
  110. TspInstrument.instance.Dispose()
  111. TspInstrument.instance = Nothing
  112. End SyncLock
  113. End If
  114. End Sub
  115. ''' <summary>
  116. ''' Creates a new default instance of this class.</summary>
  117. Public Shared Sub NewDefault(ByVal resourceTitle As String)
  118. SyncLock TspInstrument.syncLocker
  119. TspInstrument.instance = New TspInstrument(resourceTitle)
  120. End SyncLock
  121. End Sub
  122. ''' <summary>
  123. ''' The shared instance.
  124. ''' </summary>
  125. Private Shared instance As TspInstrument
  126. ''' <summary>
  127. ''' Instantiates the class.
  128. ''' </summary>
  129. ''' <returns>
  130. ''' A new or existing instance of the class.
  131. ''' </returns>
  132. ''' <remarks>
  133. ''' Use this property to instantiate a single instance of this class.
  134. ''' This class uses lazy instantiation, meaning the instance isn't
  135. ''' created until the first time it's retrieved.
  136. ''' </remarks>
  137. Public Shared Function [Get](ByVal resourceTitle As String) As TspInstrument
  138. If Not TspInstrument.Instantiated Then
  139. TspInstrument.NewDefault(resourceTitle)
  140. End If
  141. Return TspInstrument.instance
  142. End Function
  143. ''' <summary>
  144. ''' Gets True if the singleton instance was instantiated.
  145. ''' </summary>
  146. ''' <value></value>
  147. ''' <returns></returns>
  148. ''' <remarks></remarks>
  149. Public Shared ReadOnly Property Instantiated() As Boolean
  150. Get
  151. SyncLock TspInstrument.syncLocker
  152. Return TspInstrument.instance IsNot Nothing AndAlso Not TspInstrument.instance.IsDisposed
  153. End SyncLock
  154. End Get
  155. End Property
  156. #End Region
  157. #Region " ICONNECTABLE "
  158. ''' <summary>Raises the connecting event.</summary>
  159. ''' <param name="e">Passes reference to the
  160. ''' <see cref="System.ComponentModel.CancelEventArgs">cancel event arguments</see>.</param>
  161. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  162. Protected Overrides Sub OnConnecting(ByVal e As System.ComponentModel.CancelEventArgs)
  163. Dim synopsis As String = "On Connecting"
  164. ' MUST TURN OFF PROMPTS because THE TSB SYSTEM LEAVES PROMPTS ON AND RESET CLEAR DOES NOT TURN THEM OFF.
  165. Try
  166. ' allow connection time to materialize
  167. Threading.Thread.Sleep(100)
  168. Try
  169. Me.StoreTimeout(Me.ConnectTimeout)
  170. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis, "Clearing error queue.")
  171. ' clear the error queue on the controller node only.
  172. Me.ClearErrorQueue()
  173. Catch ex As Exception
  174. Me.OnMessageAvailable(TraceEventType.Information, "EXCEPTION OCCURRED CLEARING ERROR QUEUE",
  175. "Exception occurred clearing error queue. Details: {0}. Ignored.", ex)
  176. Finally
  177. Me.RestoreTimeout()
  178. End Try
  179. Try
  180. Me.StoreTimeout(Me.ConnectTimeout)
  181. ' turn prompts off. This may not be necessary.
  182. TurnPromptsErrorsOff()
  183. Catch ex As Exception
  184. Me.OnMessageAvailable(TraceEventType.Information, "EXCEPTION OCCURRED TURNING OFF PROMPTS",
  185. "Exception occurred turning off prompts. Details: {0}. Ignored.", ex)
  186. Finally
  187. Me.RestoreTimeout()
  188. End Try
  189. ' flush the input buffer in case the instrument has some left overs.
  190. DiscardUnreadData()
  191. DiscardUnsentData()
  192. ' flush write may cause the instrument to send off a new data.
  193. DiscardUnreadData()
  194. ' establish the current node as the controller node.
  195. Dim modelNumber As String = Me.QueryTrimEnd("print(localnode.model)")
  196. Dim controllerNodeNumber As Integer = Me.LocalNodeNumber
  197. Me._controllerNode = New NodeEntity(controllerNodeNumber, modelNumber, controllerNodeNumber)
  198. Catch ex As Exception
  199. Me.OnMessageAvailable(TraceEventType.Error, "EXCETION OCCURRED TURNING OFF PROMPTS AND ERRORS",
  200. "Exception occurred turning off prompts and errors. Details: {0}", ex)
  201. If e IsNot Nothing Then
  202. e.Cancel = True
  203. End If
  204. End Try
  205. MyBase.OnConnecting(e)
  206. End Sub
  207. ''' <summary>Closes the device.
  208. ''' Performs the necessary termination
  209. ''' functions, which will cleanup and disconnect the
  210. ''' interface connection.
  211. ''' </summary>
  212. ''' <history>
  213. ''' </history>
  214. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  215. Public Overrides Function Disconnect() As Boolean
  216. ' Close the device
  217. Return MyBase.Disconnect()
  218. End Function
  219. ''' <summary>Raises the disconnecting event.</summary>
  220. ''' <param name="e">Passes reference to the <see cref="System.EventArgs">event arguments</see>.</param>
  221. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  222. Protected Overrides Sub OnDisconnecting(ByVal e As System.ComponentModel.CancelEventArgs)
  223. Dim synopsis As String = "On Disconnecting"
  224. If Me.IsConnected Then
  225. Try
  226. ' send termination command
  227. If Not Me.WriteLine("localnode.prompts = 0 localnode.showerrors = 0") Then
  228. MyBase.OnMessageAvailable(TraceEventType.Warning, synopsis, "Failed turning off prompts or error messages.")
  229. End If
  230. Me.ReportVisaDeviceOperationOkay(False, synopsis, "turning off prompts or error messages")
  231. Catch ex As BaseException
  232. MyBase.OnMessageAvailable(TraceEventType.Error, synopsis, "Exception occurred turning off prompts or error messages. Details: {0}", ex)
  233. End Try
  234. End If
  235. MyBase.OnDisconnecting(e)
  236. End Sub
  237. #End Region
  238. #Region " IRESETTABLE "
  239. ''' <summary>
  240. ''' Reset known state of this instance.
  241. ''' </summary>
  242. ''' <remarks></remarks>
  243. Public Sub ResetLocalKnownState() Implements ITspInstrument.ResetLocalKnownState
  244. Me._firmwareExists = New Boolean?
  245. Me._supportfirmwareExists = New Boolean?
  246. Me._serialNumber = New Long?
  247. Me._isTspLinkOnline = New Boolean?
  248. Me._lastFetchedSavedRemoteScripts = ""
  249. End Sub
  250. #End Region
  251. #Region " IINITIALIZATABLE "
  252. Private _systemInitTimeout As Integer
  253. ''' <summary>
  254. ''' Gets or sets the time out for initializing the TSP system.
  255. ''' </summary>
  256. Public Property SystemInitTimeout() As Integer Implements ITspInstrument.SystemInitTimeout
  257. Get
  258. Return Me._systemInitTimeout
  259. End Get
  260. Set(ByVal Value As Integer)
  261. Me._systemInitTimeout = Value
  262. End Set
  263. End Property
  264. Public Function InitializeSystemState() As Boolean Implements Core.IInitializable.InitializeSystemState
  265. Try
  266. Me.StoreTimeout(Me._systemInitTimeout)
  267. Return True
  268. Catch
  269. Throw
  270. Finally
  271. Me.RestoreTimeout()
  272. End Try
  273. End Function
  274. Public Function InitializeSystemState(ByVal timeout As Integer) As Boolean Implements Core.IInitializable.InitializeSystemState
  275. Me._systemInitTimeout = timeout
  276. Return Me.InitializeSystemState
  277. End Function
  278. #End Region
  279. #Region " PROMPT HANDLING "
  280. ''' <summary>
  281. ''' Flushes the read buffer ignoring errors.
  282. ''' </summary>
  283. ''' <param name="reportUnderData">Specifies the condition for reporting unread data.</param>
  284. ''' <remarks></remarks>
  285. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  286. Private Sub _discardUnreadData(ByVal reportUnderData As Boolean)
  287. Try
  288. Me.StoreTimeout(1000)
  289. MyBase.DiscardUnreadData(10, 100, reportUnderData)
  290. Catch ex As Exception
  291. Me.OnMessageAvailable(TraceEventType.Verbose, "EXCEPTION occurred FLUSHING READ BUFFER",
  292. "Exception occurred flushing read buffer. Details: {0}. Ignored.", ex)
  293. Finally
  294. Me.RestoreTimeout()
  295. End Try
  296. End Sub
  297. Private _statusLatency As Integer
  298. ''' <summary>
  299. ''' Gets or sets the time to delay checking the instrument status. This allows the instrument
  300. ''' time to process a write command, return the status prompt and update the message and error available bits.
  301. ''' </summary>
  302. ''' <value></value>
  303. ''' <returns></returns>
  304. ''' <remarks></remarks>
  305. Public Property StatusLatency() As Integer
  306. Get
  307. Return Me._statusLatency
  308. End Get
  309. Set(ByVal value As Integer)
  310. Me._statusLatency = value
  311. End Set
  312. End Property
  313. Private _statusRepeatCount As Integer
  314. ''' <summary>
  315. ''' Gets or sets the number of time to check before returning status.
  316. ''' It seems that the instruments has some delay resetting the status that get cleared only after
  317. ''' repeated checks.
  318. ''' </summary>
  319. ''' <value></value>
  320. ''' <returns></returns>
  321. ''' <remarks></remarks>
  322. Public Property StatusRepeatCount() As Integer
  323. Get
  324. Return Me._statusRepeatCount
  325. End Get
  326. Set(ByVal value As Integer)
  327. Me._statusRepeatCount = value
  328. End Set
  329. End Property
  330. ''' <summary>Reads the device status data byte and returns True
  331. ''' if the message available bits were set.
  332. ''' Delays looking for the message status by the status latency to make sure
  333. ''' the instrument had enough time to process the previous command.
  334. ''' </summary>
  335. ''' <returns>True if the device has data in the queue
  336. ''' </returns>
  337. Public Overrides Function IsMessageAvailable() As Boolean
  338. ' wait for the instrument to process the previous command before checking the message status.
  339. If Me._statusLatency > 0 Then
  340. Threading.Thread.Sleep(Me._statusLatency)
  341. For i As Integer = 1 To Me.StatusRepeatCount
  342. MyBase.IsMessageAvailable()
  343. Next
  344. End If
  345. ' check if we have data in the queue
  346. Return MyBase.IsMessageAvailable
  347. End Function
  348. ''' <summary>
  349. ''' Flushes the read buffer.
  350. ''' </summary>
  351. ''' <remarks></remarks>
  352. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  353. Public Overloads Function DiscardUnreadData() As Boolean
  354. Dim synopsis As String = "Flushing read buffer"
  355. If Me.IsMessageAvailable Then
  356. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis, "Instrument '{0}' flushing read buffer", Me.ResourceName)
  357. End If
  358. ' flush the input buffer in case the instrument has some left overs.
  359. Try
  360. Me.StoreTimeout(1000)
  361. MyBase.DiscardUnreadData(10, 100, True)
  362. Catch ex As Exception
  363. Me.OnMessageAvailable(TraceEventType.Error, "EXCEPTION occurred FLUSHING READ BUFFER.",
  364. "Exception occurred flushing read buffer. Details: {0}", ex)
  365. Finally
  366. Me.RestoreTimeout()
  367. End Try
  368. End Function
  369. ''' <summary>
  370. ''' Flushes the read buffer.
  371. ''' </summary>
  372. ''' <remarks></remarks>
  373. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  374. Public Sub DiscardUnsentData()
  375. Try
  376. Me.StoreTimeout(1000)
  377. Me.FlushWrite()
  378. Catch ex As Exception
  379. Me.OnMessageAvailable(TraceEventType.Error, "EXCEPTION occurred FLUSHING WRITE BUFFER",
  380. "Exception occurred flushing write buffer. Details: {0}", ex)
  381. Finally
  382. Me.RestoreTimeout()
  383. End Try
  384. End Sub
  385. ''' <summary>
  386. ''' Turns off prompts and errors. It seems that the new systems come with prompts and errors off when
  387. ''' the instrument is started or reset so this is not needed.
  388. ''' </summary>
  389. ''' <remarks></remarks>
  390. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  391. Public Sub TurnPromptsErrorsOff()
  392. Dim synopsis As String = "Turning Prompts Off"
  393. ' flush the input buffer in case the instrument has some left overs.
  394. Me._discardUnreadData(True)
  395. Try
  396. ' turn off prompt transmissions
  397. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis, "Instrument '{0}' turning off automatic sending of prompt messages. Ignoring errors.", Me.ResourceName)
  398. Me.WriteLine(TspSyntax.ShowPromptsCommand(False))
  399. Catch ex As Exception
  400. Me.OnMessageAvailable(TraceEventType.Verbose, "EXCEPTION occurred TURNING OFF AUTOMATIC SENDING OF PROMPT MESSASGES",
  401. "Exception occurred turning off automatic sending of prompt messages. Details: {0}. Exception ignored.", ex)
  402. End Try
  403. ' flush again in case turning off prompts added stuff to the buffer.
  404. Me._discardUnreadData(True)
  405. Try
  406. ' turn off error transmissions
  407. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis, "Instrument '{0}' turning off automatic sending of error messages. Ignoring errors.", Me.ResourceName)
  408. Me.WriteLine(TspSyntax.ShowErrorsCommand(False))
  409. Catch ex As Exception
  410. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis,
  411. "Exception occurred turning off automatic sending of error messages. Details: {1}. Exception ignored.",
  412. Me.ResourceName, ex)
  413. End Try
  414. ' flush again in case turning off errors added stuff to the buffer.
  415. Me._discardUnreadData(True)
  416. ' flush visa and device errors
  417. ' Me.FlashVisaAndDeviceErrors(False, synopsis, "before or while turning off prompts and errors.")
  418. Me.ReportVisaDeviceOperationOkay(False, synopsis, "before or while turning off prompts and errors.")
  419. End Sub
  420. #End Region
  421. #Region " TSP: DISPLAY "
  422. ''' <summary>
  423. ''' Clears the display
  424. ''' </summary>
  425. ''' <returns></returns>
  426. ''' <remarks>
  427. ''' Sets teh display to the user mode.
  428. ''' </remarks>
  429. Public Function ClearDisplay() As Boolean Implements ITspInstrument.ClearDisplay
  430. Me._displayStatus = DisplayScreens.User
  431. If Not Me.IsDisplayExists Then
  432. Return True
  433. End If
  434. Me.WriteLine("display.clear()")
  435. Return Me.ReportVisaDeviceOperationOkay(False, "Clear Display", "clearing display")
  436. End Function
  437. ''' <summary>
  438. ''' Clears the display if not in measurement mode and set measurement mode.
  439. ''' </summary>
  440. ''' <returns></returns>
  441. ''' <remarks>
  442. ''' Sets the display to the user mode.
  443. ''' </remarks>
  444. Public Function ClearDisplayMeasurement() As Boolean
  445. If Me.IsDisplayExists Then
  446. If (Me._displayStatus And DisplayScreens.Measurement) = 0 Then
  447. Me.ClearDisplay()
  448. End If
  449. End If
  450. Me._displayStatus = DisplayScreens.Measurement
  451. Return MyBase.LastOperationOkay
  452. End Function
  453. ''' <summary>
  454. ''' Displays message on line one of the display.
  455. ''' </summary>
  456. Public Function DisplayLine(ByVal lineNumber As Integer, ByVal format As String, ByVal ParamArray args() As Object) As Boolean Implements ITspInstrument.DisplayLine
  457. Return Me.DisplayLine(lineNumber, String.Format(Globalization.CultureInfo.CurrentCulture, format, args))
  458. End Function
  459. ''' <summary>
  460. ''' Displays a message on the display.
  461. ''' </summary>
  462. ''' <param name="value"></param>
  463. ''' <returns></returns>
  464. ''' <remarks></remarks>
  465. Public Function DisplayLine(ByVal lineNumber As Integer, ByVal value As String) As Boolean Implements ITspInstrument.DisplayLine
  466. Me._displayStatus = DisplayScreens.User Or DisplayScreens.Custom
  467. If Not Me.IsDisplayExists Then
  468. Return True
  469. End If
  470. ' ignore empty strings.
  471. If String.IsNullOrEmpty(value) Then
  472. Return True
  473. End If
  474. Dim length As Integer = 20
  475. If lineNumber < 1 Then
  476. lineNumber = 1
  477. ElseIf lineNumber > 2 Then
  478. lineNumber = 2
  479. End If
  480. If lineNumber = 2 Then
  481. length = 33
  482. End If
  483. If Me.WriteLine("display.setcursor({0}, 1)", lineNumber) Then
  484. If value.Length < length Then
  485. value = value.PadRight(length)
  486. End If
  487. If Me.WriteLine("display.settext('{0}')", value) Then
  488. End If
  489. Else
  490. Return False
  491. End If
  492. Return Me.ReportVisaDeviceOperationOkay(False, "Display Line", "displaying line {0}.", lineNumber)
  493. End Function
  494. Private _displayStatus As DisplayScreens
  495. ''' <summary>
  496. ''' Gets the <see cref="DisplayScreens">display screen and status</see>.
  497. ''' </summary>
  498. ''' <remarks></remarks>
  499. Public ReadOnly Property DisplayScreen() As DisplayScreens
  500. Get
  501. Return Me._displayStatus
  502. End Get
  503. End Property
  504. ''' <summary>
  505. ''' Displays the program title.
  506. ''' </summary>
  507. ''' <param name="title">Top row data.</param>
  508. ''' <param name="subtitle">Bottom row data.</param>
  509. ''' <returns></returns>
  510. ''' <remarks></remarks>
  511. Public Function DisplayTitle(ByVal title As String, ByVal subtitle As String) As Boolean
  512. If Not Me.DisplayLine(0, title) Then
  513. Me._displayStatus = DisplayScreens.User Or DisplayScreens.Title
  514. Return False
  515. End If
  516. If Not Me.DisplayLine(2, subtitle) Then
  517. Me._displayStatus = DisplayScreens.User Or DisplayScreens.Title
  518. Return False
  519. End If
  520. Return True
  521. End Function
  522. Private _isDisplayExists As Boolean?
  523. ''' <summary>
  524. ''' Gets the display existence indicator. Some TSP instruments (e.g., 3706) may have no display.
  525. ''' </summary>
  526. ''' <value></value>
  527. ''' <returns></returns>
  528. ''' <remarks></remarks>
  529. Public ReadOnly Property IsDisplayExists() As Boolean Implements ITspInstrument.IsDisplayExists
  530. Get
  531. If Not Me._isDisplayExists.HasValue Then
  532. Try
  533. ' detect the display
  534. Me._isDisplayExists = Not Me.IsNil("display")
  535. Catch ex As isr.Visa.BaseException
  536. ' throw an exception
  537. Me.OnMessageAvailable(TraceEventType.Error, "EXCEPTION OCCURRED CHECKING DISPLAY EXISTANCE.",
  538. "Exception occurred checking display existence. Details: {0}", ex)
  539. Me._isDisplayExists = False
  540. Finally
  541. End Try
  542. End If
  543. Return Me._isDisplayExists.Value
  544. End Get
  545. End Property
  546. ''' <summary>
  547. ''' Restores the instrument display to its main mode.
  548. ''' </summary>
  549. ''' <returns></returns>
  550. ''' <remarks></remarks>
  551. Public Function RestoreDisplay() As Boolean Implements ITspInstrument.RestoreDisplay
  552. Me._displayStatus = DisplayScreens.Default
  553. If Not Me.IsDisplayExists Then
  554. Return True
  555. End If
  556. ' Documentation error: Display Main equals 1, not 0. This code should work on
  557. ' other instruments.
  558. Me.WriteLine("display.screen = display.MAIN or 0")
  559. Return Me.ReportVisaDeviceOperationOkay(False, "Restore Display", "restoring display")
  560. End Function
  561. #End Region
  562. #Region " TSP: ERRORS "
  563. Private _showErrors As Nullable(Of Boolean)
  564. ''' <summary>Gets the condition for showing errors.
  565. ''' </summary>
  566. Public ReadOnly Property ShowErrors() As Nullable(Of Boolean) Implements ITspInstrument.ShowErrors
  567. Get
  568. Return Me._showErrors
  569. End Get
  570. End Property
  571. ''' <summary>Returns the condition for showing errors.
  572. ''' When true, the unit will automatically display the errors stored in the
  573. ''' error queue, and then clear the queue. Errors will be processed at the
  574. ''' end of executing a command message (just prior to issuing a prompt if
  575. ''' prompts are enabled).
  576. ''' When false, errors will not display. Errors will be left in the error
  577. ''' queue and must be explicitly read or cleared. The error prompt (TSP?)
  578. ''' is enabled.
  579. ''' </summary>
  580. ''' <param name="access"></param>
  581. ''' <returns></returns>
  582. ''' <remarks></remarks>
  583. Public Function ShowErrorsGetter(ByVal access As isr.Visa.ResourceAccessLevels) As Boolean Implements ITspInstrument.ShowErrorsGetter
  584. If (access = Visa.ResourceAccessLevels.Device) OrElse Not Me._showErrors.HasValue Then
  585. If Me.WriteQueryLine(TspSyntax.ShowErrorsQueryCommand) Then
  586. If Me.RaiseVisaOrDeviceException("failed getting error prompts status") Then
  587. Me._showErrors = 1 = Me.ReadInt32().Value
  588. End If
  589. End If
  590. Me.RaiseVisaOrDeviceException("failed getting error prompts status")
  591. End If
  592. Return Me._showErrors.Value
  593. End Function
  594. ''' <summary>Sets the condition for showing errors.
  595. ''' When true, the unit will automatically display the errors stored in the
  596. ''' error queue, and then clear the queue. Errors will be processed at the
  597. ''' end of executing a command message (just prior to issuing a prompt if
  598. ''' prompts are enabled).
  599. ''' When false, errors will not display. Errors will be left in the error
  600. ''' queue and must be explicitly read or cleared. The error prompt (TSP?)
  601. ''' is enabled.
  602. ''' </summary>
  603. ''' <param name="access"></param>
  604. ''' <param name="value"></param>
  605. ''' <returns></returns>
  606. ''' <remarks></remarks>
  607. Public Function ShowErrorsSetter(ByVal value As Boolean, ByVal access As isr.Visa.ResourceAccessLevels) As Boolean Implements ITspInstrument.ShowErrorsSetter
  608. If (access = Visa.ResourceAccessLevels.Device) OrElse (Not Me._showErrors.HasValue) OrElse (value <> showErrors.Value) Then
  609. ' now send the command. This will also update the status.
  610. If Me.WriteLine(TspSyntax.ShowErrorsCommand(value)) Then
  611. Me._showErrors = value
  612. End If
  613. Me.RaiseVisaOrDeviceException("failed setting error prompts status to {0}", value)
  614. End If
  615. Return Me._showErrors.Value
  616. End Function
  617. #End Region
  618. #Region " TSP: GLOBAL "
  619. ''' <summary>
  620. ''' Sends a collect garbage command.
  621. ''' </summary>
  622. Public Function CollectGarbage() As Boolean Implements ITspInstrument.CollectGarbage
  623. ' send the message
  624. Return Me.WriteLine(TspSyntax.CollectGarbageCommand)
  625. End Function
  626. ''' <summary>
  627. ''' Collects garbage on the specified node.
  628. ''' </summary>
  629. ''' <param name="nodeNumber">Specifies the node number.</param>
  630. ''' <returns></returns>
  631. ''' <remarks></remarks>
  632. Public Function CollectGarbage(ByVal nodeNumber As Integer) As Boolean Implements ITspInstrument.CollectGarbage
  633. ' send the message
  634. Return Me.WriteLine(TspSyntax.CollectNodeGarbage, nodeNumber)
  635. End Function
  636. #End Region
  637. #Region " TSP: NODE "
  638. ''' <summary>
  639. ''' Gets the error count on a remote node.
  640. ''' </summary>
  641. ''' <param name="nodeNumber"></param>
  642. ''' <returns></returns>
  643. ''' <remarks></remarks>
  644. Public Overloads Function ErrorQueueCount(ByVal nodeNumber As Integer) As Integer
  645. If nodeNumber <= 1 Then
  646. Return MyBase.ErrorQueueCount(Visa.ResourceAccessLevels.Device)
  647. Else
  648. Dim count As Integer? = Me.QueryInt32("print(string.format('%d',node[{0}].errorqueue.count)) waitcomplete()", nodeNumber)
  649. If Me.ReportVisaOperationOkay("Fetch error queue count", "Failed fetching error queue count from node {0}", nodeNumber) Then
  650. Return count.Value
  651. Else
  652. Return 0
  653. End If
  654. End If
  655. End Function
  656. ''' <summary>
  657. ''' Fetches the error queue.
  658. ''' </summary>
  659. ''' <param name="nodeNumber"></param>
  660. ''' <returns></returns>
  661. ''' <remarks>Error messages are formatted as follows:<para>
  662. ''' Error #,message,level=#.</para>
  663. ''' <list type="bullet">
  664. ''' <listheader><description>Error levels are:</description>
  665. ''' </listheader>
  666. ''' <item><description>0 - Informational.</description></item>
  667. ''' <item><description>10 - Informational.</description></item>
  668. ''' <item><description>30 - Serious.</description></item>
  669. ''' <item><description>40 - Critical.</description></item>
  670. ''' </list>
  671. ''' </remarks>
  672. Public Function DequeueErrorQueue(ByVal nodeNumber As Integer) As String
  673. If nodeNumber <= 1 Then
  674. Return MyBase.ErrorQueue(Visa.ResourceAccessLevels.Device)
  675. Else
  676. Dim errors As New System.Text.StringBuilder(2048)
  677. Do While Me.ErrorQueueCount(nodeNumber) > 0
  678. Dim message As String = Me.QueryPrintFormat(String.Format(Globalization.CultureInfo.CurrentCulture,
  679. "error %d,%s,level=%d,node{0}", nodeNumber),
  680. String.Format(Globalization.CultureInfo.CurrentCulture,
  681. "node[{0}].errorqueue.next()", nodeNumber))
  682. If Me.ReportVisaDeviceOperationOkay(True, "dequeue node error", "failed dequeuing errors from node {0}", nodeNumber) Then
  683. errors.AppendFormat(Globalization.CultureInfo.CurrentCulture,
  684. "{0},node={1}", message, nodeNumber)
  685. errors.AppendLine()
  686. Else
  687. errors.AppendFormat(Globalization.CultureInfo.CurrentCulture,
  688. "Error occurred fetching error queue element from node {0}", nodeNumber)
  689. errors.AppendLine()
  690. Return errors.ToString
  691. End If
  692. Loop
  693. Return errors.ToString
  694. End If
  695. End Function
  696. ''' <summary>
  697. ''' Dequeues errors on all nodes.
  698. ''' </summary>
  699. ''' <returns></returns>
  700. ''' <remarks></remarks>
  701. Public Function DequeueErrorQueue() As String
  702. Dim builder As New isr.Core.MyStringBuilder
  703. For Each node As NodeEntity In Me._nodeEntities
  704. If Me.ErrorQueueCount(node.Number) > 0 Then
  705. Dim errors As String = Me.DequeueErrorQueue(node.Number)
  706. If Not String.IsNullOrEmpty(errors) Then
  707. builder.AppendLine("Node #{0} errors: {1}", node.Number, errors)
  708. End If
  709. End If
  710. Next
  711. Return builder.ToString
  712. End Function
  713. ''' <summary>
  714. ''' Reports if a device error occurred as set the <see cref="LastOperationOkay">success condition</see>
  715. ''' Can only be used after receiving a full reply from the instrument.
  716. ''' </summary>
  717. ''' <param name="nodeNumber">Specifies the node number.</param>
  718. ''' <param name="synopsis">Specifies a synopsis for the warning if an error occurred.</param>
  719. ''' <param name="format">Specifies the report format.</param>
  720. ''' <param name="args">Specifies the report arguments.</param>
  721. ''' <returns>True if success</returns>
  722. ''' <remarks></remarks>
  723. Public Function ReportDeviceOperationOkay(ByVal nodeNumber As Integer, ByVal synopsis As String,
  724. ByVal format As String, ByVal ParamArray args() As Object) As Boolean Implements ITspInstrument.ReportDeviceOperationOkay
  725. MyBase.ReportVisaDeviceOperationOkay(False, synopsis, format, args)
  726. If nodeNumber > 1 AndAlso Me.ErrorQueueCount(nodeNumber) > 0 Then
  727. Me.LastOperationOkay = False
  728. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{1}' encountered errors {0}. Details:{3}{2}{3}{4}",
  729. String.Format(Globalization.CultureInfo.CurrentCulture, format, args),
  730. Me.ResourceName,
  731. Me.DequeueErrorQueue(nodeNumber),
  732. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  733. End If
  734. Return Me.LastOperationOkay
  735. End Function
  736. ''' <summary>
  737. ''' Makes a script nil and returns true if the script was nilified.
  738. ''' Does not check if the script exists.
  739. ''' </summary>
  740. ''' <param name="nodeNumber">Specifies the remote node number.</param>
  741. ''' <param name="name">Specifies the script name</param>
  742. ''' <returns></returns>
  743. ''' <remarks>Assumes the script is known to exist.
  744. ''' Waits till completion.
  745. ''' </remarks>
  746. Private Function _nilifyScript(ByVal nodeNumber As Integer, ByVal name As String) As Boolean
  747. If String.IsNullOrEmpty(name) Then
  748. Return False
  749. End If
  750. Dim synopsis As String = "Nullifying Script"
  751. ' ignore errors as failure is handled below.
  752. Me.ExecuteCommandWaitComplete(nodeNumber, Me._nilifyTimeout, False, "{0} = nil", name)
  753. ' allow the next command to create an error if wait complete times out.
  754. If Me.IsNil(nodeNumber, name) Then
  755. Return True
  756. Else
  757. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' script {1} still exists on node {2} after nil.{3}{4}",
  758. Me.ResourceName, name, nodeNumber,
  759. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  760. Return False
  761. End If
  762. End Function
  763. ''' <summary>
  764. ''' Makes a script nil and returns true if the script was nullified.
  765. ''' </summary>
  766. ''' <param name="nodeNumber">Specifies the remote node number.</param>
  767. ''' <param name="name">Specifies the script name</param>
  768. ''' <returns></returns>
  769. ''' <remarks></remarks>
  770. Public Function NilifyScript(ByVal nodeNumber As Integer, ByVal name As String) As Boolean Implements ITspInstrument.NilifyScript
  771. If String.IsNullOrEmpty(name) Then
  772. Return False
  773. End If
  774. If Me.IsNil(nodeNumber, name) Then
  775. Return True
  776. Else
  777. Return Me._nilifyScript(nodeNumber, name)
  778. End If
  779. End Function
  780. ''' <summary>
  781. ''' Sets the connect rule on the specified node.
  782. ''' </summary>
  783. ''' <param name="nodeNumber">Specifies the remote node number.</param>
  784. ''' <param name="value"></param>
  785. ''' <returns></returns>
  786. ''' <remarks></remarks>
  787. Public Function ConnectRuleSetter(ByVal nodeNumber As Integer, ByVal value As Integer) As Boolean Implements ITspInstrument.ConnectRuleSetter
  788. Return Me.WriteLine(TspSyntax.ConnectRuleSetter, nodeNumber, value)
  789. End Function
  790. ''' <summary>
  791. ''' Deletes the <paramref name="name">specified</paramref> script.
  792. ''' Also nilifies the script if delete command worked.
  793. ''' </summary>
  794. ''' <param name="nodeNumber">Specifies the remote node number.</param>
  795. ''' <param name="name">Specifies the script name</param>
  796. ''' <returns></returns>
  797. ''' <remarks></remarks>
  798. Public Function DeleteScript(ByVal nodeNumber As Integer, ByVal name As String, ByVal refreshScriptCatalog As Boolean) As Boolean Implements ITspInstrument.DeleteScript
  799. If String.IsNullOrEmpty(name) Then
  800. Return False
  801. End If
  802. If Me.SavedScriptExists(nodeNumber, name, refreshScriptCatalog) Then
  803. Return Me.DeleteSavedScript(nodeNumber, name)
  804. Else
  805. Return Me.NilifyScript(nodeNumber, name)
  806. End If
  807. End Function
  808. ''' <summary>
  809. ''' Deletes the <paramref name="name">specified</paramref> script.
  810. ''' Also nilifies the script if delete command worked.
  811. ''' </summary>
  812. ''' <param name="node">Specifies the node.</param>
  813. ''' <param name="name">Specifies the script name</param>
  814. ''' <returns></returns>
  815. ''' <remarks></remarks>
  816. Public Function DeleteScript(ByVal node As INodeEntity, ByVal name As String, ByVal refreshScriptCatalog As Boolean) As Boolean
  817. If node Is Nothing Then
  818. Throw New ArgumentNullException("node")
  819. End If
  820. If String.IsNullOrEmpty(name) Then
  821. Return False
  822. End If
  823. If node.IsController Then
  824. Return DeleteScript(name, refreshScriptCatalog)
  825. Else
  826. Return DeleteScript(node.Number, name, refreshScriptCatalog)
  827. End If
  828. End Function
  829. ''' <summary>
  830. ''' Deletes the <paramref name="name">specified</paramref> saved script.
  831. ''' Also nilifies the script if delete command worked.
  832. ''' Then checks if the script was deleted and if so returns true.
  833. ''' Otherwise, returns false.
  834. ''' </summary>
  835. ''' <param name="nodeNumber">Specifies the remote node number.</param>
  836. ''' <param name="name">Specifies the script name</param>
  837. ''' <returns></returns>
  838. ''' <remarks>Presumes the saved script exists.
  839. ''' Waits for operation completion.
  840. ''' </remarks>
  841. Public Function DeleteSavedScript(ByVal nodeNumber As Integer, ByVal name As String) As Boolean
  842. If String.IsNullOrEmpty(name) Then
  843. Return False
  844. End If
  845. Dim synopsis As String = "Deleting Saved Script"
  846. ' failure is handled below.
  847. Me.ExecuteCommandWaitComplete(nodeNumber, Me.DeleteTimeout, False, "script.delete('{0}')", name)
  848. ' make script nil
  849. If Me.NilifyScript(nodeNumber, name) Then
  850. ' make sure to re-check that script is gone.
  851. If Me.SavedScriptExists(nodeNumber, name, True) Then
  852. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' saved script {1} still exists after nil on node {2}{3}{4}",
  853. Me.ResourceName, name, nodeNumber,
  854. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  855. Return False
  856. Else
  857. Return True
  858. End If
  859. Else
  860. Return False
  861. End If
  862. End Function
  863. ''' <summary>
  864. ''' Deletes the <paramref name="name">specified</paramref> saved script.
  865. ''' Also nilifies the script if delete command worked.
  866. ''' Returns true if the script was deleted.
  867. ''' </summary>
  868. ''' <param name="nodeNumber">Specifies the remote node number.</param>
  869. ''' <param name="name">Specifies the script name</param>
  870. ''' <returns></returns>
  871. ''' <remarks>
  872. ''' Waits for operation completion.
  873. ''' </remarks>
  874. Public Function DeleteSavedScript(ByVal nodeNumber As Integer, ByVal name As String, ByVal refreshScriptCatalog As Boolean) As Boolean Implements ITspInstrument.DeleteSavedScript
  875. If String.IsNullOrEmpty(name) Then
  876. Return False
  877. End If
  878. Dim synopsis As String = "Deleting Saved Script"
  879. If Me.SavedScriptExists(nodeNumber, name, refreshScriptCatalog) Then
  880. ' execute command but ignore errors as they are handled below.
  881. Me.ExecuteCommandWaitComplete(nodeNumber, Me.DeleteTimeout, False, "script.delete('{0}')", name)
  882. ' make script nil
  883. If Me.NilifyScript(nodeNumber, name) Then
  884. ' make sure to re-check that script is gone.
  885. If Me.SavedScriptExists(nodeNumber, name, True) Then
  886. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' saved script {1} still exists after nil on node {2}{3}{4}",
  887. Me.ResourceName, name, nodeNumber,
  888. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  889. Return False
  890. Else
  891. Return True
  892. End If
  893. Else
  894. Return False
  895. End If
  896. Else
  897. Return True
  898. End If
  899. End Function
  900. ''' <summary>
  901. ''' Executes a command on the node.
  902. ''' </summary>
  903. ''' <param name="nodeNumber">Specifies the node number.</param>
  904. ''' <param name="isQuery">Specifies the condition indicating if the command is a query, which determines how errors are fetched.</param>
  905. ''' <param name="format">Specifies the command format.</param>
  906. ''' <param name="args">Specifies the command arguments.</param>
  907. ''' <returns></returns>
  908. ''' <remarks></remarks>
  909. Public Function ExecuteCommandWaitComplete(ByVal nodeNumber As Integer,
  910. ByVal timeout As Integer,
  911. ByVal isQuery As Boolean,
  912. ByVal format As String,
  913. ByVal ParamArray args() As Object) As Boolean
  914. Dim synopsis As String = "Execute node command"
  915. Dim command As String = String.Format(Globalization.CultureInfo.CurrentCulture, format, args)
  916. If Me.WriteLine(TspSyntax.ExecuteCommand, nodeNumber, command) Then
  917. IssueWaitComplete(0)
  918. Me.AwaitOperationCompleted(timeout, timeout \ 10 + 10)
  919. If isQuery Then
  920. If Not ReportVisaOperationOkay(synopsis, "executing '{0}' on node {1}", command, nodeNumber) Then
  921. Return False
  922. End If
  923. Else
  924. If Not ReportDeviceOperationOkay(nodeNumber, synopsis, "executing '{0}' on node {1}", command, nodeNumber) Then
  925. Return False
  926. End If
  927. End If
  928. Else
  929. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed executing '{1}' on node {2}.{3}{4}",
  930. Me.ResourceName, command, nodeNumber,
  931. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  932. Return False
  933. End If
  934. Return True
  935. End Function
  936. ''' <summary>
  937. ''' Executes a command on the node.
  938. ''' </summary>
  939. ''' <param name="node">Specifies the node.</param>
  940. ''' <param name="isQuery">Specifies the condition indicating if the command is a query, which determines how errors are fetched.
  941. ''' While the remote command will not return values, the local node may.</param>
  942. ''' <param name="format">Specifies the command format.</param>
  943. ''' <param name="args">Specifies the command arguments.</param>
  944. ''' <returns></returns>
  945. ''' <remarks></remarks>
  946. Public Function ExecuteCommandWaitComplete(ByVal node As INodeEntity,
  947. ByVal timeout As Integer,
  948. ByVal isQuery As Boolean,
  949. ByVal format As String,
  950. ByVal ParamArray args() As Object) As Boolean
  951. If node Is Nothing Then
  952. Throw New ArgumentNullException("node")
  953. End If
  954. If node.IsController Then
  955. Dim synopsis As String = "Execute node command"
  956. Dim command As String = String.Format(Globalization.CultureInfo.CurrentCulture, format, args)
  957. If Me.WriteLine(format, args) Then
  958. IssueWaitComplete(0)
  959. Me.AwaitOperationCompleted(timeout, timeout \ 10 + 10)
  960. If isQuery Then
  961. If Not ReportVisaOperationOkay(synopsis, "executing '{0}' on node {1}", command, node.Number) Then
  962. Return False
  963. End If
  964. Else
  965. If Not ReportDeviceOperationOkay(node.Number, synopsis, "executing '{0}' on node {1}", command, node.Number) Then
  966. Return False
  967. End If
  968. End If
  969. Else
  970. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed executing '{1}' on node {2}.{3}{4}",
  971. Me.ResourceName, command, node.Number,
  972. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  973. Return False
  974. End If
  975. Return True
  976. Else
  977. Return Me.ExecuteCommandWaitComplete(node.Number, timeout, isQuery, format, args)
  978. End If
  979. End Function
  980. ''' <summary>
  981. ''' Executes a command on the remote node. This leaves an item in the input buffer that must be retried.
  982. ''' </summary>
  983. ''' <param name="nodeNumber">Specifies the remote node number.</param>
  984. ''' <param name="format">Specifies the command format.</param>
  985. ''' <param name="args">Specifies the command arguments.</param>
  986. ''' <returns></returns>
  987. ''' <remarks></remarks>
  988. Public Function ExecuteValueGetter(ByVal nodeNumber As Integer, ByVal format As String, ByVal ParamArray args() As Object) As Boolean Implements ITspInstrument.ExecuteValueGetter
  989. If String.IsNullOrEmpty(format) Then
  990. Throw New ArgumentNullException("format")
  991. Else
  992. Return Me.WriteLine(TspSyntax.ValueGetterCommand1, nodeNumber,
  993. String.Format(Globalization.CultureInfo.CurrentCulture, format, args))
  994. End If
  995. Return False
  996. End Function
  997. Private _lastFetchedSavedRemoteScripts As String
  998. ''' <summary>
  999. ''' Gets a comma-separated and comma-terminated list of the saved scripts
  1000. ''' that was fetched last from the remote node. A new script is fetched after save and delete.
  1001. ''' </summary>
  1002. ''' <value></value>
  1003. ''' <returns></returns>
  1004. ''' <remarks></remarks>
  1005. Public ReadOnly Property LastFetchedSavedRemoteScripts() As String Implements ITspInstrument.LastFetchedSavedRemoteScripts
  1006. Get
  1007. Return Me._lastFetchedSavedRemoteScripts
  1008. End Get
  1009. End Property
  1010. ''' <summary>
  1011. ''' Fetches the list of saved scripts and saves it in the <see cref="LastFetchedSavedScripts"></see>
  1012. ''' </summary>
  1013. ''' <returns></returns>
  1014. ''' <remarks></remarks>
  1015. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  1016. Public Function FetchSavedScripts(ByVal nodeNumber As Integer) As Boolean Implements ITspInstrument.FetchSavedScripts
  1017. Dim synopsis As String = "Fetch Saved Scripts"
  1018. Try
  1019. Me.StoreTimeout(Me._saveTimeout)
  1020. Me._lastFetchedSavedRemoteScripts = ""
  1021. If Me.WriteQueryLine(TspSyntax.ValueGetterCommand2, nodeNumber, TspSyntax.ScriptCatalogGetterCommand, "names") Then
  1022. If Me.ReportVisaDeviceOperationOkay(True, "Fetch Node Saved Scripts", "Failed fetching catalog from node {0}", nodeNumber) Then
  1023. Me._lastFetchedSavedRemoteScripts = Me.ReadLineTrimEnd
  1024. Else
  1025. Return False
  1026. End If
  1027. If String.IsNullOrEmpty(Me._lastFetchedSavedRemoteScripts) Then
  1028. Me._lastFetchedSavedRemoteScripts = ""
  1029. End If
  1030. End If
  1031. Return ReportDeviceOperationOkay(nodeNumber, synopsis, "Failed fetching catalog from node {0}", nodeNumber)
  1032. Catch
  1033. Throw
  1034. Finally
  1035. MyBase.RestoreTimeout()
  1036. End Try
  1037. End Function
  1038. ''' <summary>
  1039. ''' Fetches the list of saved scripts and saves it in the <see cref="LastFetchedSavedScripts"></see>
  1040. ''' </summary>
  1041. ''' <param name="node">Specifies the node.</param>
  1042. ''' <returns></returns>
  1043. ''' <remarks></remarks>
  1044. Public Function FetchSavedScripts(ByVal node As INodeEntity) As Boolean
  1045. If node Is Nothing Then
  1046. Throw New ArgumentNullException("node")
  1047. End If
  1048. If node.IsController Then
  1049. Return FetchSavedScripts()
  1050. Else
  1051. Return FetchSavedScripts(node.Number)
  1052. End If
  1053. End Function
  1054. ''' <summary>
  1055. ''' Executes a command on the remote node and retrieves a string.
  1056. ''' </summary>
  1057. ''' <param name="nodeNumber">Specifies the remote node number to validate.</param>
  1058. ''' <param name="format">Specifies the command format.</param>
  1059. ''' <param name="args">Specifies the command arguments.</param>
  1060. ''' <returns></returns>
  1061. ''' <remarks></remarks>
  1062. Public Function GetString(ByVal nodeNumber As Integer, ByVal format As String, ByVal ParamArray args() As Object) As String Implements ITspInstrument.GetString
  1063. If Me.ExecuteValueGetter(nodeNumber, format, args) Then
  1064. Return MyBase.ReadLineTrimEnd()
  1065. Else
  1066. Return ""
  1067. End If
  1068. End Function
  1069. ''' <summary>
  1070. ''' Executes a command on the remote node and retrieves a string.
  1071. ''' </summary>
  1072. ''' <param name="nodeNumber">Specifies the remote node number to validate.</param>
  1073. ''' <param name="format">Specifies the command format.</param>
  1074. ''' <param name="args">Specifies the command arguments.</param>
  1075. ''' <returns></returns>
  1076. ''' <remarks></remarks>
  1077. Public Function GetBoolean(ByVal nodeNumber As Integer, ByVal format As String, ByVal ParamArray args() As Object) As Boolean? Implements ITspInstrument.GetBoolean
  1078. If Me.ExecuteValueGetter(nodeNumber, format, args) Then
  1079. Return MyBase.ReadBoolean
  1080. Else
  1081. Return New Boolean?
  1082. End If
  1083. End Function
  1084. ''' <summary>
  1085. ''' Checks the series of values and return true if any one of them is nil.
  1086. ''' </summary>
  1087. ''' <param name="nodeNumber">Specifies the remote node number to validate.</param>
  1088. ''' <param name="values">Specifies a list of nil objects to check.</param>
  1089. ''' <returns></returns>
  1090. ''' <remarks></remarks>
  1091. Public Function IsNil(ByVal nodeNumber As Integer, ByVal ParamArray values() As String) As Boolean Implements ITspInstrument.IsNil
  1092. If values Is Nothing OrElse values.Length = 0 Then
  1093. Throw New ArgumentNullException("values")
  1094. Else
  1095. For Each value As String In values
  1096. If Not String.IsNullOrEmpty(value) Then
  1097. Dim outcome As Boolean? = Me.GetBoolean(nodeNumber, "{0}==nil", value)
  1098. If outcome.HasValue AndAlso outcome.Value Then
  1099. Return True
  1100. End If
  1101. End If
  1102. Next
  1103. End If
  1104. Return False
  1105. End Function
  1106. ''' <summary>
  1107. ''' Checks the series of values and return true if any one of them is nil.
  1108. ''' </summary>
  1109. ''' <param name="node">Specifies the node.</param>
  1110. ''' <param name="values">Specifies a list of nil objects to check.</param>
  1111. ''' <returns></returns>
  1112. ''' <remarks></remarks>
  1113. Public Function IsNil(ByVal node As INodeEntity, ByVal ParamArray values() As String) As Boolean Implements ITspInstrument.IsNil
  1114. If node Is Nothing Then
  1115. Throw New ArgumentNullException("node")
  1116. End If
  1117. If node.IsController Then
  1118. Return Me.IsNil(values)
  1119. Else
  1120. Return Me.IsNil(node.Number, values)
  1121. End If
  1122. End Function
  1123. ''' <summary>
  1124. ''' Loops until the name is found or timeout.
  1125. ''' </summary>
  1126. ''' <param name="nodeNumber">Specifies the node number</param>
  1127. ''' <param name="name">Specifies the script name</param>
  1128. ''' <param name="timeout"></param>
  1129. ''' <returns></returns>
  1130. ''' <remarks></remarks>
  1131. Private Function WaitNotNil(ByVal nodeNumber As Integer, ByVal name As String, ByVal timeout As Integer) As Boolean
  1132. ' verify that the script exists.
  1133. Dim endTime As DateTime = DateTime.Now.AddMilliseconds(timeout)
  1134. Dim detected As Boolean = Not Me.IsNil(nodeNumber, name)
  1135. Do Until detected OrElse DateTime.Now > endTime
  1136. Windows.Forms.Application.DoEvents()
  1137. Threading.Thread.Sleep(10)
  1138. detected = Not Me.IsNil(nodeNumber, name)
  1139. Loop
  1140. Return detected
  1141. End Function
  1142. ''' <summary>
  1143. ''' Resets the local TSP node.
  1144. ''' </summary>
  1145. ''' <returns></returns>
  1146. ''' <remarks></remarks>
  1147. Public Function ResetNode() As Boolean
  1148. Me.WriteLine("localnode.reset()")
  1149. Me.ReportVisaDeviceOperationOkay(False, "Reset Node", "resetting local TSP node")
  1150. End Function
  1151. ''' <summary>
  1152. ''' Resets a remote node.
  1153. ''' </summary>
  1154. ''' <returns></returns>
  1155. ''' <remarks></remarks>
  1156. Public Function ResetNode(ByVal nodeNumber As Integer) As Boolean
  1157. Dim synopsis As String = "Reset Node"
  1158. Dim details As String = "resetting TSP node {0}"
  1159. Me.WriteLine("node[{0}].reset()", nodeNumber)
  1160. Return Me.ReportDeviceOperationOkay(nodeNumber, synopsis, details, nodeNumber)
  1161. End Function
  1162. ''' <summary>
  1163. ''' Resets a node.
  1164. ''' </summary>
  1165. ''' <returns></returns>
  1166. ''' <remarks></remarks>
  1167. Public Function ResetNode(ByVal node As INodeEntity) As Boolean
  1168. If node Is Nothing Then
  1169. Throw New ArgumentNullException("node")
  1170. End If
  1171. If node.IsController Then
  1172. Return Me.ResetNode()
  1173. Else
  1174. Return Me.ResetNode(node.Number)
  1175. End If
  1176. End Function
  1177. ''' <summary>
  1178. ''' Loads the binary script function for creating binary scripts.
  1179. ''' </summary>
  1180. ''' <returns></returns>
  1181. ''' <remarks>
  1182. ''' Non-A instruments require having a special function for creating the binary scripts.
  1183. ''' </remarks>
  1184. Private Function LoadBinaryScriptsFunction(ByVal node As INodeEntity) As Boolean
  1185. If node Is Nothing Then
  1186. Throw New ArgumentNullException("node")
  1187. End If
  1188. Const scriptName As String = "CreateBinaries"
  1189. Using script As New ScriptEntity(scriptName, Tsp.NodeEntity.ModelFamilyMask(Tsp.InstrumentModelFamily.K2600))
  1190. script.Source = EmbeddedResourceManager.EmbeddedTextResourceGetter("BinaryScripts.tsp")
  1191. Return Me.LoadRunUserScript(script, node)
  1192. End Using
  1193. End Function
  1194. ''' <summary>
  1195. ''' Returns true if the script is a binary script.
  1196. ''' </summary>
  1197. ''' <param name="name">Specifies the name of the script.</param>
  1198. ''' <param name="node">Specifies the node entity.</param>
  1199. ''' <returns></returns>
  1200. ''' <remarks></remarks>
  1201. Public Function IsBinaryScript(ByVal name As String, ByVal node As INodeEntity) As Boolean
  1202. If node Is Nothing Then
  1203. Throw New ArgumentNullException("node")
  1204. End If
  1205. If node.IsController Then
  1206. Return Me.IsStatementTrue("_G.isr.script.isBinary({0})", name)
  1207. Else
  1208. Return Me.IsStatementTrue("_G.isr.script.isBinary({0},{1})", name, node.Number)
  1209. End If
  1210. End Function
  1211. ''' <summary>
  1212. ''' Converts the script to binary format.
  1213. ''' Returns true if the script was converted.
  1214. ''' </summary>
  1215. ''' <param name="node">Specifies the node entity.</param>
  1216. ''' <param name="name">Specifies the script name</param>
  1217. ''' <returns></returns>
  1218. ''' <remarks>
  1219. ''' Waits for operation completion.
  1220. ''' </remarks>
  1221. Public Function ConvertBinaryScript(ByVal name As String, ByVal node As INodeEntity) As Boolean
  1222. If node Is Nothing Then
  1223. Throw New ArgumentNullException("node")
  1224. End If
  1225. If String.IsNullOrEmpty(name) Then
  1226. Return False
  1227. ElseIf Me.IsBinaryScript(name, node) Then
  1228. Return True
  1229. End If
  1230. Dim synopsis As String = "Convert Binary Script"
  1231. If node.InstrumentModelFamily = InstrumentModelFamily.K2600A OrElse
  1232. node.InstrumentModelFamily = InstrumentModelFamily.K3700 Then
  1233. If Me.ExecuteCommandWaitComplete(node, Me.SaveTimeout, False, "{0}.source = nil waitcomplete()", name) Then
  1234. End If
  1235. Return Me.ReportVisaDeviceOperationOkay(False, synopsis, "creating binary script '{0}' on node {1}", name, node.Number)
  1236. Else
  1237. ' non-A instruments require having a special function for creating the binary scripts.
  1238. If Me.LoadBinaryScriptsFunction(node) Then
  1239. ' create the binary script.
  1240. If Me.ExecuteCommandWaitComplete(node, Me.SaveTimeout, False, "CreateBinaryScript('{0}', {1}) waitcomplete()",
  1241. name, name) Then
  1242. Dim fullName As String = "script.user.scripts." & name
  1243. If Me.WaitNotNil(node.Number, fullName, Me._saveTimeout) Then
  1244. ' assign the new script name
  1245. If Me.ExecuteCommandWaitComplete(node, Me.SaveTimeout, False,
  1246. "{0} = nil waitcomplete() {0} = {1} waitcomplete()", name, fullName) Then
  1247. If Me.WaitNotNil(node.Number, name, Me._saveTimeout) Then
  1248. If IsBinaryScript(name, node) Then
  1249. Return True
  1250. Else
  1251. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed creating binary script '{1}' reference to script '{2}' on node {3}--new script not found on the remote node.{4}{5}",
  1252. Me.ResourceName, name, fullName, node.Number,
  1253. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  1254. End If
  1255. Else
  1256. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed creating script '{1}' reference to script '{2}' on node {3}--new script not found on the remote node.{4}{5}",
  1257. Me.ResourceName, name, fullName, node.Number,
  1258. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  1259. Return False
  1260. End If
  1261. Else
  1262. If Me.ReportVisaDeviceOperationOkay(False, synopsis, "creating script script '{0}'", name) Then
  1263. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed creating reference to script '{1}' using '{2}' on node {3}--new script not found on the remote node.{4}{5}",
  1264. Me.ResourceName, fullName, name, node.Number,
  1265. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  1266. End If
  1267. Return False
  1268. End If
  1269. Else
  1270. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed creating script '{1}' from script {2} on node {3}--new script not found on the remote node.{4}{5}",
  1271. Me.ResourceName, fullName, name, node.Number,
  1272. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  1273. Return False
  1274. End If
  1275. ElseIf Me.ReportVisaDeviceOperationOkay(False, synopsis, "loading binary scripts function") Then
  1276. ' report failure if not an instrument or VISA error (handler returns Okay.)
  1277. ' report failure if not an instrument or VISA error (handler returns Okay.)
  1278. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed creating binary script {1}.{2}{3}",
  1279. Me.ResourceName, name,
  1280. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  1281. Return False
  1282. Else
  1283. Return False
  1284. End If
  1285. Else
  1286. Return False
  1287. End If
  1288. End If
  1289. Return True
  1290. End Function
  1291. ''' <summary>
  1292. ''' Saves the specifies script to non-volatile memory.
  1293. ''' Returns true if the script was saved.
  1294. ''' </summary>
  1295. ''' <param name="node">Specifies the node entity.</param>
  1296. ''' <param name="name">Specifies the script name</param>
  1297. ''' <param name="isSaveAsBinary">Specifies the condition requesting clearing the source before saving</param>
  1298. ''' <param name="isBootScript">Specifies the condition indicating if this is a boot script</param>
  1299. ''' <returns></returns>
  1300. ''' <remarks>
  1301. ''' Waits for operation completion.
  1302. ''' </remarks>
  1303. Public Function SaveScript(ByVal name As String, ByVal node As INodeEntity, ByVal isSaveAsBinary As Boolean, ByVal isBootScript As Boolean) As Boolean Implements ITspInstrument.SaveScript
  1304. If node Is Nothing Then
  1305. Throw New ArgumentNullException("node")
  1306. End If
  1307. If String.IsNullOrEmpty(name) Then
  1308. Return False
  1309. End If
  1310. ' saving just the script name does not work if script was created and name assigned.
  1311. Dim commandFormat As String = "script.user.scripts.{0}.save() waitcomplete()"
  1312. If isSaveAsBinary Then
  1313. If Not Me.ConvertBinaryScript(name, node) Then
  1314. Return False
  1315. End If
  1316. End If
  1317. If isBootScript Then
  1318. commandFormat = "script.user.scripts.{0}.autorun = 'yes' " & commandFormat
  1319. End If
  1320. If node.IsController Then
  1321. Me.EnableWaitComplete()
  1322. If Me.WriteLine(commandFormat, name) Then
  1323. Me.AwaitOperationCompleted(Me.SaveTimeout, Me.SaveTimeout \ 10 + 10)
  1324. End If
  1325. Else
  1326. If Me.ExecuteCommandWaitComplete(node.Number, Me.SaveTimeout, False, commandFormat, name) Then
  1327. End If
  1328. End If
  1329. Return Me.SavedScriptExists(name, node, True)
  1330. End Function
  1331. ''' <summary>
  1332. ''' Returns true if the specified script exists as a saved script on the remote node.
  1333. ''' </summary>
  1334. ''' <param name="name">Specifies the script name</param>
  1335. ''' <returns></returns>
  1336. ''' <remarks></remarks>
  1337. Public Function LastSavedRemoteScriptExists(ByVal name As String) As Boolean Implements ITspInstrument.LastSavedRemoteScriptExists
  1338. If String.IsNullOrEmpty(name) Then
  1339. Return False
  1340. End If
  1341. Return Me._lastFetchedSavedRemoteScripts.IndexOf(name & ",", 0, StringComparison.OrdinalIgnoreCase) >= 0
  1342. End Function
  1343. ''' <summary>
  1344. ''' Returns true if the specified script exists as a saved script.
  1345. ''' </summary>
  1346. ''' <param name="nodeNumber">Specifies the remote node number to validate.</param>
  1347. ''' <param name="name">Specifies the script name</param>
  1348. ''' <param name="refreshScriptCatalog">True to refresh the list of saved scripts.</param>
  1349. ''' <returns></returns>
  1350. ''' <remarks></remarks>
  1351. Public Function SavedScriptExists(ByVal nodeNumber As Integer, ByVal name As String, ByVal refreshScriptCatalog As Boolean) As Boolean Implements ITspInstrument.SavedScriptExists
  1352. If refreshScriptCatalog Then
  1353. Me.FetchSavedScripts(nodeNumber)
  1354. End If
  1355. Return LastSavedRemoteScriptExists(name)
  1356. End Function
  1357. ''' <summary>
  1358. ''' Returns true if the specified script exists as a saved script.
  1359. ''' </summary>
  1360. ''' <param name="name">Specifies the script name</param>
  1361. ''' <param name="node">Specifies the node to validate.</param>
  1362. ''' <param name="refreshScriptCatalog">True to refresh the list of saved scripts.</param>
  1363. ''' <returns></returns>
  1364. ''' <remarks></remarks>
  1365. Public Function SavedScriptExists(ByVal name As String, ByVal node As INodeEntity, ByVal refreshScriptCatalog As Boolean) As Boolean Implements ITspInstrument.SavedScriptExists
  1366. If node Is Nothing Then
  1367. Throw New ArgumentNullException("node")
  1368. End If
  1369. If node.IsController Then
  1370. Return SavedScriptExists(name, refreshScriptCatalog)
  1371. Else
  1372. Return SavedScriptExists(node.Number, name, refreshScriptCatalog)
  1373. End If
  1374. End Function
  1375. Private _serialNumberReading As String = ""
  1376. ''' <summary>
  1377. ''' Reads and returns the instrument serial number
  1378. ''' </summary>
  1379. ''' <returns></returns>
  1380. ''' <remarks></remarks>
  1381. Public Function ReadSerialNumber() As String
  1382. Me._serialNumberReading = Me.QueryPrintFormat("%d", "localnode.serialno").Trim
  1383. Return Me._serialNumberReading
  1384. End Function
  1385. Private _serialNumber As Long?
  1386. ''' <summary>
  1387. ''' Reads and returns the instrument serial number
  1388. ''' </summary>
  1389. ''' <returns></returns>
  1390. ''' <remarks></remarks>
  1391. Public Function SerialNumber() As Long
  1392. If Not Me._serialNumber.HasValue Then
  1393. Dim numericValue As Long = 0
  1394. If Long.TryParse(Me.ReadSerialNumber, Globalization.NumberStyles.Number, Globalization.CultureInfo.InvariantCulture, numericValue) Then
  1395. Me._serialNumber = numericValue
  1396. End If
  1397. Me._serialNumber = numericValue
  1398. End If
  1399. Return Me._serialNumber.Value
  1400. End Function
  1401. #End Region
  1402. #Region " TSP: NODES "
  1403. Private _controllerNode As INodeEntity
  1404. ''' <summary>
  1405. ''' Gets reference to the controller node.
  1406. ''' </summary>
  1407. ''' <value></value>
  1408. ''' <returns></returns>
  1409. ''' <remarks></remarks>
  1410. Public ReadOnly Property ControllerNode() As INodeEntity
  1411. Get
  1412. Return Me._controllerNode
  1413. End Get
  1414. End Property
  1415. Private _nodeEntities As NodeEntityCollection
  1416. ''' <summary>
  1417. ''' Returns the enumerated list of node entities.
  1418. ''' </summary>
  1419. ''' <returns></returns>
  1420. ''' <remarks></remarks>
  1421. Public Function NodeEntities() As NodeEntityCollection Implements ITspInstrument.NodeEntities
  1422. Return Me._nodeEntities
  1423. End Function
  1424. Private _maximumNodeCount As Integer
  1425. ''' <summary>
  1426. ''' Gets the maximum number of node to iterate when enumerating nodes.
  1427. ''' </summary>
  1428. ''' <value></value>
  1429. ''' <returns></returns>
  1430. ''' <remarks></remarks>
  1431. Public Property MaximumNodeCount() As Integer
  1432. Get
  1433. Return Me._actualNodeCount
  1434. End Get
  1435. Set(ByVal value As Integer)
  1436. Me._actualNodeCount = value
  1437. End Set
  1438. End Property
  1439. Private _actualNodeCount As Integer
  1440. ''' <summary>
  1441. ''' Gets the number of nodes detected in the system.
  1442. ''' </summary>
  1443. ''' <value></value>
  1444. ''' <returns></returns>
  1445. ''' <remarks></remarks>
  1446. Public ReadOnly Property ActualNodeCount() As Integer
  1447. Get
  1448. Return Me._actualNodeCount
  1449. End Get
  1450. End Property
  1451. ''' <summary>
  1452. ''' Enumerates the collection of nodes on the TSP Link net.
  1453. ''' </summary>
  1454. ''' <param name="nodeCount">Specifies the maximum expected node number.
  1455. ''' There could be up to 64 nodes on the TSP link. Specify 0 to use the maximum node count.</param>
  1456. ''' <remarks></remarks>
  1457. Public Function EnumerateNodes(ByVal nodeCount As Integer) As Boolean
  1458. Dim synopsis As String = "Enumerating nodes"
  1459. Me._actualNodeCount = 0
  1460. If nodeCount <= 0 Then
  1461. nodeCount = Me._maximumNodeCount
  1462. End If
  1463. Me._nodeEntities = New NodeEntityCollection()
  1464. Dim controllerNodeNumber As Integer = Me.LocalNodeNumber
  1465. If nodeCount = 1 Then
  1466. Me._actualNodeCount = 1
  1467. Dim modelNumber As String = Me.QueryTrimEnd("print(localnode.model)")
  1468. Me._controllerNode = New NodeEntity(Me.LocalNodeNumber, modelNumber, controllerNodeNumber)
  1469. If Me._controllerNode.InstrumentModelFamily = InstrumentModelFamily.None Then
  1470. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument model {0} has no defined instrument family.{1}{2}",
  1471. modelNumber,
  1472. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  1473. Else
  1474. Me._nodeEntities.Add(Me._controllerNode)
  1475. End If
  1476. Else
  1477. For i As Integer = 1 To nodeCount
  1478. If Not Me.IsStatementTrue("node[{0}] == nil", i) Then
  1479. If Me.ReportVisaDeviceOperationOkay(False, synopsis, "Failed enumerating nodes") Then
  1480. Me._actualNodeCount += 1
  1481. ' set the group number.
  1482. Dim modelNumber As String = Me.QueryTrimEnd("print(node[{0}].model)", i)
  1483. Dim node As Tsp.INodeEntity = New NodeEntity(i, modelNumber, controllerNodeNumber)
  1484. node.FirmwareVersion = Me.QueryTrimEnd("print(node[{0}].revision)", i)
  1485. node.SerialNumber = Me.QueryTrimEnd("print(node[{0}].serialno)", i)
  1486. Me.OnMessageAvailable(TraceEventType.Information, synopsis, "Instrument model {0} S/N={1} Firmware={2} enumerated on node {3}.",
  1487. node.ModelNumber, node.SerialNumber, node.FirmwareVersion, node.Number)
  1488. If i = controllerNodeNumber Then
  1489. Me._controllerNode = node
  1490. End If
  1491. If node.InstrumentModelFamily = InstrumentModelFamily.None Then
  1492. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument model {0} has no defined instrument family.{1}{2}",
  1493. modelNumber,
  1494. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  1495. Else
  1496. Me._nodeEntities.Add(node)
  1497. End If
  1498. End If
  1499. End If
  1500. Next
  1501. End If
  1502. Return Me._nodeEntities.Count = Me._actualNodeCount
  1503. End Function
  1504. #End Region
  1505. #Region " TSP OPC "
  1506. ''' <summary>
  1507. ''' Waits for completion of last operation.
  1508. ''' </summary>
  1509. ''' <param name="timeout"></param>
  1510. ''' <param name="pollDelay"></param>
  1511. ''' <returns>True if operation completed within the specified timeout.</returns>
  1512. ''' <remarks>
  1513. ''' Assumes requesting service event is registered with the instrument.
  1514. ''' </remarks>
  1515. Public Function AwaitOperationCompleted(ByVal timeout As Integer, ByVal pollDelay As Integer) As Boolean
  1516. Me.AwaitServiceRequest(Visa.Ieee4882.ServiceRequests.RequestingService, timeout, pollDelay)
  1517. Me.ReportVisaDeviceOperationOkay(False, "Await Completion", "waiting operation completion. Error ignored.")
  1518. Return Not Me.TimedOut
  1519. End Function
  1520. ''' <summary>
  1521. ''' Enabled detection of completion.
  1522. ''' </summary>
  1523. ''' <returns></returns>
  1524. ''' <remarks>
  1525. ''' 3475. Add Or Visa.Ieee4882.ServiceRequests.OperationEvent
  1526. ''' </remarks>
  1527. Public Function EnableWaitComplete() As Boolean
  1528. Return Me.EnableServiceRequestComplete(Visa.Ieee4882.StandardEvents.All And Not Visa.Ieee4882.StandardEvents.RequestControl,
  1529. Visa.Ieee4882.ServiceRequests.StandardEvent)
  1530. End Function
  1531. ''' <summary>
  1532. ''' Issues wait complete for the node.
  1533. ''' </summary>
  1534. ''' <returns></returns>
  1535. ''' <remarks></remarks>
  1536. Public Function IssueWaitComplete() As Boolean
  1537. If Me.EnableWaitComplete Then
  1538. Return Me.WriteLine("waitcomplete()")
  1539. Else
  1540. Return False
  1541. End If
  1542. End Function
  1543. ''' <summary>
  1544. ''' Issues wait complete for the group.
  1545. ''' </summary>
  1546. ''' <param name="groupNumber">Specifies the group number. That would be the same as the
  1547. ''' TSP Link group number for the node.</param>
  1548. ''' <returns></returns>
  1549. ''' <remarks></remarks>
  1550. Public Function IssueWaitComplete(ByVal groupNumber As Integer) As Boolean
  1551. If Me.EnableWaitComplete Then
  1552. Return Me.WriteLine("waitcomplete({0})", groupNumber)
  1553. Else
  1554. Return False
  1555. End If
  1556. End Function
  1557. ''' <summary>
  1558. ''' Queries the instrument and returns true if received an operation completed value (1).
  1559. ''' </summary>
  1560. ''' <returns></returns>
  1561. ''' <remarks></remarks>
  1562. Public Function IsOperationCompleted() As Boolean
  1563. IsOperationCompleted = Me.OperationCompleted(Visa.ResourceAccessLevels.Device)
  1564. Me.ReportVisaDeviceOperationOkay(False, "Read OPC value", "reading OPC value. Error ignored.")
  1565. End Function
  1566. #End Region
  1567. #Region " TSP LINK "
  1568. #Region " DATA QUEUE "
  1569. ''' <summary>
  1570. ''' clears the data queue for the specified node.
  1571. ''' </summary>
  1572. ''' <param name="nodeNumber"></param>
  1573. ''' <returns></returns>
  1574. ''' <remarks></remarks>
  1575. Public Function ClearDataQueue(ByVal nodeNumber As Integer, ByVal reportQueueNotEmpty As Boolean) As Boolean
  1576. If IsStatementTrue("node[{0}] == nil", nodeNumber) Then
  1577. Return True
  1578. Else
  1579. If reportQueueNotEmpty Then
  1580. If DataQueueCount(nodeNumber) > 0 Then
  1581. Me.OnMessageAvailable(TraceEventType.Information, "Clear Data Queue", "Data queue not empty on node {0}", nodeNumber)
  1582. Return MyBase.WriteLine("node[{0}].dataqueue.clear() waitcomplete({0})", nodeNumber)
  1583. End If
  1584. Else
  1585. Return MyBase.WriteLine("node[{0}].dataqueue.clear() waitcomplete({0})", nodeNumber)
  1586. End If
  1587. End If
  1588. Return True
  1589. End Function
  1590. ''' <summary>
  1591. ''' Clears dataqueue on all nodes.
  1592. ''' </summary>
  1593. ''' <returns></returns>
  1594. ''' <remarks></remarks>
  1595. Public Function ClearDataQueue(ByVal reportQueueNotEmpty As Boolean) As Boolean
  1596. Dim success As Boolean = True
  1597. If Me._nodeEntities IsNot Nothing Then
  1598. For Each node As INodeEntity In Me._nodeEntities
  1599. If Not ClearDataQueue(node.Number, reportQueueNotEmpty) Then
  1600. success = False
  1601. End If
  1602. Next
  1603. End If
  1604. Return success
  1605. End Function
  1606. ''' <summary>
  1607. ''' Returns true if the node dataqueue has elements in it.
  1608. ''' </summary>
  1609. ''' <param name="nodeNumber"></param>
  1610. ''' <returns></returns>
  1611. ''' <remarks></remarks>
  1612. Public Function DataQueueCapacity(ByVal nodeNumber As Integer) As Integer
  1613. If IsStatementTrue("node[{0}] == nil", nodeNumber) Then
  1614. Return 0
  1615. Else
  1616. Dim count As String = Me.QueryPrintFormat("%d", String.Format(Globalization.CultureInfo.CurrentCulture,
  1617. "node[{0}].dataqueue.capacity", nodeNumber))
  1618. Dim value As Integer = 0
  1619. If Integer.TryParse(count, Globalization.NumberStyles.Number, Globalization.CultureInfo.CurrentCulture, value) Then
  1620. Return value
  1621. Else
  1622. Return 0
  1623. End If
  1624. End If
  1625. End Function
  1626. ''' <summary>
  1627. ''' Returns true if the node dataqueue has elements in it.
  1628. ''' </summary>
  1629. ''' <param name="nodeNumber"></param>
  1630. ''' <returns></returns>
  1631. ''' <remarks></remarks>
  1632. Public Function DataQueueCount(ByVal nodeNumber As Integer) As Integer
  1633. If IsStatementTrue("node[{0}] == nil", nodeNumber) Then
  1634. Return 0
  1635. Else
  1636. Dim count As String = Me.QueryPrintFormat("%d", String.Format(Globalization.CultureInfo.CurrentCulture,
  1637. "node[{0}].dataqueue.count", nodeNumber))
  1638. Dim value As Integer = 0
  1639. If Integer.TryParse(count, Globalization.NumberStyles.Number, Globalization.CultureInfo.CurrentCulture, value) Then
  1640. Return value
  1641. Else
  1642. Return 0
  1643. End If
  1644. End If
  1645. End Function
  1646. #End Region
  1647. #Region " ERROR QUEUE "
  1648. ''' <summary>
  1649. ''' Clears the error queue for the specified node.
  1650. ''' </summary>
  1651. ''' <param name="nodeNumber"></param>
  1652. ''' <returns></returns>
  1653. ''' <remarks></remarks>
  1654. Public Overloads Function ClearErrorQueue(ByVal nodeNumber As Integer) As Boolean
  1655. If IsStatementTrue("node[{0}] == nil", nodeNumber) Then
  1656. Return True
  1657. Else
  1658. Return MyBase.WriteLine("node[{0}].errorqueue.clear() waitcomplete({0})", nodeNumber)
  1659. End If
  1660. End Function
  1661. ''' <summary>
  1662. ''' Clears error queue on all nodes or the controller if no nodes are defined.
  1663. ''' </summary>
  1664. ''' <returns></returns>
  1665. ''' <remarks></remarks>
  1666. Public Overrides Function ClearErrorQueue() As Boolean
  1667. Dim success As Boolean = True
  1668. If Me._nodeEntities Is Nothing Then
  1669. MyBase.ClearErrorQueue()
  1670. Else
  1671. For Each node As INodeEntity In Me._nodeEntities
  1672. If Not ClearErrorQueue(node.Number) Then
  1673. success = False
  1674. End If
  1675. Next
  1676. End If
  1677. Return success
  1678. End Function
  1679. #End Region
  1680. Private _usingTspLink As Boolean
  1681. ''' <summary>
  1682. ''' Gets or sets the condition for using TSP Link.
  1683. ''' Must be affirmative otherwise TSP link reset commands are ignored.
  1684. ''' </summary>
  1685. ''' <value></value>
  1686. ''' <returns></returns>
  1687. ''' <remarks></remarks>
  1688. Public Property UsingTspLink() As Boolean
  1689. Get
  1690. Return Me._usingTspLink
  1691. End Get
  1692. Set(ByVal value As Boolean)
  1693. Me._usingTspLink = value
  1694. End Set
  1695. End Property
  1696. Private _isTspLinkOnline As Boolean?
  1697. ''' <summary>
  1698. ''' Checks if TSP System is ready.
  1699. ''' </summary>
  1700. ''' <value></value>
  1701. ''' <returns></returns>
  1702. ''' <remarks></remarks>
  1703. Public ReadOnly Property IsTspLinkOnline() As Boolean
  1704. Get
  1705. If Me._usingTspLink Then
  1706. If Not Me._isTspLinkOnline.HasValue Then
  1707. Me._isTspLinkOnline = Me.IsStatementTrue("tsplink.state == 'online'")
  1708. End If
  1709. Else
  1710. Me._isTspLinkOnline = False
  1711. End If
  1712. Return Me._isTspLinkOnline.Value
  1713. End Get
  1714. End Property
  1715. ''' <summary>
  1716. ''' Assigns group numbers to the nodes.
  1717. ''' A unique group number is required for executing
  1718. ''' concurrent code on all nodes.
  1719. ''' </summary>
  1720. ''' <returns></returns>
  1721. ''' <remarks></remarks>
  1722. ''' <history date="09/08/2009" by="David Hary" revision="3.0.3538.x">
  1723. ''' Allows setting groups even if TSP Link is not on line.
  1724. ''' </history>
  1725. Public Function AssignNodeGroupNumbers() As Boolean
  1726. If Me._nodeEntities IsNot Nothing Then
  1727. For Each node As INodeEntity In Me._nodeEntities
  1728. If Me.IsTspLinkOnline Then
  1729. Me.WriteLine("node[{0}].tsplink.group = {0}", node.Number)
  1730. Else
  1731. Me.WriteLine("localnode.tsplink.group = {0}", node.Number)
  1732. End If
  1733. If Not Me.ReportVisaDeviceOperationOkay(False, "Assign group numbers", "Failed assigning group to node number {0}", node.Number) Then
  1734. Return False
  1735. End If
  1736. Next
  1737. 'If Me.IsTspLinkOnline Then
  1738. 'End If
  1739. End If
  1740. Return True
  1741. End Function
  1742. ''' <summary>
  1743. ''' Reset TSP Link with error reporting.
  1744. ''' </summary>
  1745. ''' <returns></returns>
  1746. ''' <remarks></remarks>
  1747. ''' <history date="09/22/2009" by="David Hary" revision="3.0.3552.x">
  1748. ''' The procedure caused error 1220 - TSP link failure on the remote instrument. The error occurred only
  1749. ''' if the program was stopped and restarted without toggling power on the instruments.
  1750. ''' Waiting completion of the previous task helped even though that task did not access the remote node!
  1751. ''' </history>
  1752. Private Function _resetTspLinkIgnoreError() As Boolean
  1753. Dim synopsis As String = "Resetting TSP Link"
  1754. Me._isTspLinkOnline = New Boolean?
  1755. Me.IssueWaitComplete(0)
  1756. If Not Me.AwaitOperationCompleted(Me.SaveTimeout, Me.SaveTimeout \ 10 + 10) Then
  1757. Me.OnMessageAvailable(TraceEventType.Information, synopsis, "Instrument '{0}' timed out awaiting completion before reseting TSP Link. Failure ignored.{1}{2}",
  1758. Me.ResourceName,
  1759. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  1760. End If
  1761. Me.EnableWaitComplete()
  1762. If Me.WriteLine("tsplink.reset() waitcomplete(0) errorqueue.clear() waitcomplete()") Then
  1763. If Not Me.AwaitOperationCompleted(Me.SaveTimeout, Me.SaveTimeout \ 10 + 10) Then
  1764. Me.OnMessageAvailable(TraceEventType.Information, synopsis, "Instrument '{0}' timed out awaiting completion after reseting TSP Link. Failure ignored.{1}{2}",
  1765. Me.ResourceName,
  1766. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  1767. End If
  1768. Else
  1769. If Me.ReportVisaDeviceOperationOkay(False, synopsis, "Failed sending the TSP Link reset command.") Then
  1770. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed sending the TSP Link reset command.{1}{2}",
  1771. Me.ResourceName,
  1772. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  1773. End If
  1774. Return False
  1775. End If
  1776. Return True
  1777. End Function
  1778. ''' <summary>
  1779. ''' Reset TSP Link with error reporting.
  1780. ''' </summary>
  1781. ''' <returns></returns>
  1782. ''' <remarks></remarks>
  1783. <CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")>
  1784. Private Function _resetTspLinkReportError() As Boolean
  1785. Dim synopsis As String = "Resetting TSP Link"
  1786. Me._isTspLinkOnline = New Boolean?
  1787. Me.EnableWaitComplete()
  1788. If Me.WriteLine("tsplink.reset() waitcomplete(0)") Then
  1789. If Me.AwaitOperationCompleted(Me.SaveTimeout, Me.SaveTimeout \ 10 + 10) Then
  1790. If Not Me.ReportVisaDeviceOperationOkay(False, synopsis, "Failed resetting TSP Link") Then
  1791. Return False
  1792. End If
  1793. Else
  1794. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed awaiting completion after reseting TSP Link.{1}{2}",
  1795. Me.ResourceName,
  1796. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  1797. Return False
  1798. End If
  1799. Else
  1800. If Me.ReportVisaDeviceOperationOkay(False, synopsis, "Failed resetting TSP Link") Then
  1801. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed reseting TSP Link.{1}{2}",
  1802. Me.ResourceName,
  1803. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  1804. End If
  1805. Return False
  1806. End If
  1807. End Function
  1808. ''' <summary>
  1809. ''' Resets the TSP link if not on line.
  1810. ''' </summary>
  1811. ''' <returns></returns>
  1812. ''' <remarks></remarks>
  1813. ''' <history date="09/08/2009" by="David Hary" revision="3.0.3538.x">
  1814. ''' Allows to complete TSP Link reset even on failure in case we have a single node.
  1815. ''' </history>
  1816. Public Function ResetTspLink() As Boolean
  1817. Me._nodeEntities = New NodeEntityCollection()
  1818. If Me._usingTspLink Then
  1819. If Not Me._resetTspLinkIgnoreError() Then
  1820. Return False
  1821. End If
  1822. End If
  1823. If Me.IsTspLinkOnline Then
  1824. ' enumerate all nodes.
  1825. If Not Me.EnumerateNodes(0) Then
  1826. Return False
  1827. End If
  1828. ' enumerate the controller node.
  1829. ElseIf Not Me.EnumerateNodes(1) Then
  1830. Return False
  1831. End If
  1832. ' assign node group numbers.
  1833. Me.AssignNodeGroupNumbers()
  1834. ' clear the error queue on all nodes.
  1835. Me.ClearErrorQueue()
  1836. ' clear data queues.
  1837. Me.ClearDataQueue(True)
  1838. Return True
  1839. End Function
  1840. #End Region
  1841. #Region " TSP: PROMPTS "
  1842. Private _showPrompts As Nullable(Of Boolean)
  1843. ''' <summary>Gets the condition for showing prompts.
  1844. ''' </summary>
  1845. Public ReadOnly Property ShowPrompts() As Nullable(Of Boolean) Implements ITspInstrument.ShowPrompts
  1846. Get
  1847. Return Me._showPrompts
  1848. End Get
  1849. End Property
  1850. ''' <summary>Return the condition for showing prompts.
  1851. ''' Controls prompting.
  1852. ''' When true, prompts are issued after each command message is
  1853. ''' processed by the instrument.
  1854. ''' When false prompts are not issued.
  1855. ''' Command messages do not generate prompts. Rather, the TSP instrument
  1856. ''' generates prompts in response to command messages.
  1857. ''' When prompting is enabled, the instrument generates prompts in
  1858. ''' response to command messages. There are three prompts that might be
  1859. ''' returned:
  1860. ''' “TSP>” is the standard prompt. This prompt indicates that everything is
  1861. ''' normal and the command is done processing.
  1862. ''' “TSP?” is issued if there are entries in the error queue when the prompt
  1863. ''' is issued. Like the “TSP>” prompt, it indicates the command is done
  1864. ''' processing. It does not mean the previous command generated an error,
  1865. ''' only that there are still errors in the queue when the command was done
  1866. ''' processing.
  1867. ''' “>>>>” is the continuation prompt. This prompt is used when downloading
  1868. ''' scripts or flash images. When downloading scripts or flash images, many
  1869. ''' command messages must be sent as a unit. The continuation prompt indicates
  1870. ''' that the instrument is expecting more messages as part of the current
  1871. ''' command.
  1872. ''' </summary>
  1873. ''' <param name="access"></param>
  1874. ''' <returns></returns>
  1875. ''' <remarks></remarks>
  1876. Public Function ShowPromptsGetter(ByVal access As isr.Visa.ResourceAccessLevels) As Boolean Implements ITspInstrument.ShowPromptsGetter
  1877. If (access = Visa.ResourceAccessLevels.Device) OrElse Not Me._showPrompts.HasValue Then
  1878. If Me.WriteQueryLine(TspSyntax.ShowPromptsQueryCommand) Then
  1879. If Me.RaiseVisaOrDeviceException("failed getting the condition for showing prompts.") Then
  1880. Me._showPrompts = 1 = Me.ReadInt32().Value
  1881. End If
  1882. End If
  1883. Me.RaiseVisaOrDeviceException("failed getting the condition for showing prompts.")
  1884. End If
  1885. Return Me._showPrompts.Value
  1886. End Function
  1887. ''' <summary>Sets the condition for showing prompts.
  1888. ''' Controls prompting.
  1889. ''' When true, prompts are issued after each command message is
  1890. ''' processed by the instrument.
  1891. ''' When false prompts are not issued.
  1892. ''' Command messages do not generate prompts. Rather, the TSP instrument
  1893. ''' generates prompts in response to command messages.
  1894. ''' When prompting is enabled, the instrument generates prompts in
  1895. ''' response to command messages. There are three prompts that might be
  1896. ''' returned:
  1897. ''' “TSP>” is the standard prompt. This prompt indicates that everything is
  1898. ''' normal and the command is done processing.
  1899. ''' “TSP?” is issued if there are entries in the error queue when the prompt
  1900. ''' is issued. Like the “TSP>” prompt, it indicates the command is done
  1901. ''' processing. It does not mean the previous command generated an error,
  1902. ''' only that there are still errors in the queue when the command was done
  1903. ''' processing.
  1904. ''' “>>>>” is the continuation prompt. This prompt is used when downloading
  1905. ''' scripts or flash images. When downloading scripts or flash images, many
  1906. ''' command messages must be sent as a unit. The continuation prompt indicates
  1907. ''' that the instrument is expecting more messages as part of the current
  1908. ''' command.
  1909. ''' </summary>
  1910. ''' <param name="access"></param>
  1911. ''' <param name="value"></param>
  1912. ''' <returns></returns>
  1913. ''' <remarks></remarks>
  1914. Public Function ShowPromptsSetter(ByVal value As Boolean, ByVal access As isr.Visa.ResourceAccessLevels) As Boolean Implements ITspInstrument.ShowPromptsSetter
  1915. If (access = Visa.ResourceAccessLevels.Device) OrElse (Not Me._showPrompts.HasValue) OrElse (value <> showPrompts.Value) Then
  1916. Dim previousValue As Nullable(Of Boolean) = Me._showErrors
  1917. Me._showPrompts = value
  1918. ' now send the command. This will also update the status.
  1919. If Not Me.WriteLine(TspSyntax.ShowPromptsCommand(value)) Then
  1920. Me._showErrors = previousValue
  1921. End If
  1922. Me.RaiseVisaOrDeviceException("failed setting the condition for showing prompts.")
  1923. End If
  1924. Return Me._showPrompts.Value
  1925. End Function
  1926. #End Region
  1927. #Region " TSP SCRIPTS "
  1928. ''' <summary>
  1929. ''' Deletes the <paramref name="name">specified</paramref> script.
  1930. ''' Also nilifies the script if delete command worked.
  1931. ''' </summary>
  1932. ''' <param name="name">Specifies the script name</param>
  1933. ''' <returns></returns>
  1934. ''' <remarks></remarks>
  1935. Public Function DeleteScript(ByVal name As String, ByVal refreshScriptCatalog As Boolean) As Boolean Implements ITspInstrument.DeleteScript
  1936. If String.IsNullOrEmpty(name) Then
  1937. Return False
  1938. End If
  1939. If Me.SavedScriptExists(name, refreshScriptCatalog) Then
  1940. Return Me.DeleteSavedScript(name)
  1941. Else
  1942. Return Me.NilifyScript(name)
  1943. End If
  1944. End Function
  1945. ''' <summary>
  1946. ''' Deletes the <paramref name="name">specified</paramref> saved script.
  1947. ''' Also nilifies the script if delete command worked.
  1948. ''' Returns true if the script was deleted.
  1949. ''' </summary>
  1950. ''' <param name="name">Specifies the script name</param>
  1951. ''' <returns></returns>
  1952. ''' <remarks>Assumes the script is known to exist.
  1953. ''' Waits for operation completion.
  1954. ''' </remarks>
  1955. Public Function DeleteSavedScript(ByVal name As String) As Boolean
  1956. If String.IsNullOrEmpty(name) Then
  1957. Return False
  1958. End If
  1959. Me.EnableWaitComplete()
  1960. Dim synopsis As String = "Deleting Saved Script"
  1961. If Me.WriteLine("script.delete('{0}') waitcomplete()", name) Then
  1962. ' make script nil
  1963. Me.AwaitOperationCompleted(Me.DeleteTimeout, Me.DeleteTimeout \ 10 + 10)
  1964. If Me.NilifyScript(name) Then
  1965. ' make sure to re-check that script is gone.
  1966. If Me.SavedScriptExists(name, True) Then
  1967. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' script {1} still exists after nil.{2}{3}",
  1968. Me.ResourceName, name,
  1969. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  1970. Return False
  1971. Else
  1972. Return True
  1973. End If
  1974. Else
  1975. Return False
  1976. End If
  1977. Else
  1978. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' sending the command to delete script {1}.{2}{3}",
  1979. Me.ResourceName, name,
  1980. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  1981. Return False
  1982. End If
  1983. End Function
  1984. ''' <summary>
  1985. ''' Deletes the <paramref name="name">specified</paramref> saved script.
  1986. ''' Also nilifies the script if delete command worked.
  1987. ''' </summary>
  1988. ''' <param name="name">Specifies the script name</param>
  1989. ''' <returns></returns>
  1990. ''' <remarks></remarks>
  1991. Public Function DeleteSavedScript(ByVal name As String, ByVal refreshScriptCatalog As Boolean) As Boolean Implements ITspInstrument.DeleteSavedScript
  1992. If String.IsNullOrEmpty(name) Then
  1993. Return False
  1994. End If
  1995. If Me.SavedScriptExists(name, refreshScriptCatalog) Then
  1996. Return DeleteSavedScript(name)
  1997. Else
  1998. Return True
  1999. End If
  2000. End Function
  2001. Private _deleteTimeout As Integer
  2002. ''' <summary>
  2003. ''' Gets or sets the time out for deleting a script.
  2004. ''' </summary>
  2005. Public Property DeleteTimeout() As Integer
  2006. Get
  2007. Return Me._deleteTimeout
  2008. End Get
  2009. Set(ByVal Value As Integer)
  2010. Me._deleteTimeout = Value
  2011. End Set
  2012. End Property
  2013. ''' <summary>
  2014. ''' Fetches the list of saved scripts and saves it in the <see cref="LastFetchedSavedScripts"></see>
  2015. ''' </summary>
  2016. ''' <returns></returns>
  2017. ''' <remarks></remarks>
  2018. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  2019. Public Function FetchSavedScripts() As Boolean Implements ITspInstrument.FetchSavedScripts
  2020. Try
  2021. MyBase.StoreTimeout(Me._saveTimeout)
  2022. Me._lastFetchedSavedScripts = ""
  2023. If Me.WriteQueryLine("do {0} print( names ) end ", TspSyntax.ScriptCatalogGetterCommand) Then
  2024. If Me.ReportVisaDeviceOperationOkay(True, "Fetch Saved Scripts", "Failed fetching catalog") Then
  2025. Me._lastFetchedSavedScripts = Me.ReadLineTrimEnd
  2026. Else
  2027. Return False
  2028. End If
  2029. If String.IsNullOrEmpty(Me._lastFetchedSavedScripts) Then
  2030. Me._lastFetchedSavedScripts = ""
  2031. End If
  2032. End If
  2033. Return Me.ReportVisaDeviceOperationOkay(True, "Fetch Saved Scripts", "Failed fetching catalog. Timeout={0}", MyBase.Timeout)
  2034. Catch
  2035. Throw
  2036. Finally
  2037. MyBase.RestoreTimeout()
  2038. End Try
  2039. End Function
  2040. Private _lastFetchedSavedScripts As String = ""
  2041. ''' <summary>
  2042. ''' Gets a comma-separated and comma-terminated list of the saved scripts
  2043. ''' that was fetched last. A new script is fetched after save and delete.
  2044. ''' </summary>
  2045. ''' <value></value>
  2046. ''' <returns></returns>
  2047. ''' <remarks></remarks>
  2048. Public ReadOnly Property LastFetchedSavedScripts() As String Implements ITspInstrument.LastFetchedSavedScripts
  2049. Get
  2050. Return Me._lastFetchedSavedScripts
  2051. End Get
  2052. End Property
  2053. Private _lastFetchScriptSource As String
  2054. ''' <summary>
  2055. ''' Gets the last source fetched from the instrument
  2056. ''' </summary>
  2057. ''' <value></value>
  2058. ''' <returns></returns>
  2059. ''' <remarks></remarks>
  2060. Public ReadOnly Property LastFetchScriptSource() As String Implements ITspInstrument.LastFetchScriptSource
  2061. Get
  2062. Return Me._lastFetchScriptSource
  2063. End Get
  2064. End Property
  2065. ''' <summary>
  2066. ''' Fetches the <paramref name="value">specified</paramref> script source.
  2067. ''' </summary>
  2068. ''' <param name="name">Specifies the script name.</param>
  2069. ''' <returns></returns>
  2070. ''' <remarks>
  2071. ''' No longer trimming spaces as this caused failure to load script to the 2602.
  2072. ''' </remarks>
  2073. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  2074. Public Function FetchScriptSource(ByVal name As String) As Boolean Implements ITspInstrument.FetchScriptSource
  2075. Dim synopsis As String = "Fetch Script Source"
  2076. Me._lastFetchScriptSource = ""
  2077. If String.IsNullOrEmpty(name) Then
  2078. Return False
  2079. End If
  2080. Try
  2081. If Me.WriteLine("isr.script.list({0})", name) Then
  2082. ' give the instrument time to get the code.
  2083. Threading.Thread.Sleep(500)
  2084. Me._lastFetchScriptSource = MyBase.ReadLines(10, 400, True)
  2085. #If True Then
  2086. ' trap non-empty buffer.
  2087. Try
  2088. If Me.IsMessageAvailable Then
  2089. Debug.Assert(Not Debugger.IsAttached, "Buffer not empty")
  2090. End If
  2091. IsStatementTrue("node[{0}] == nil", 1)
  2092. Catch
  2093. Debug.Assert(Not Debugger.IsAttached, "Buffer not empty")
  2094. End Try
  2095. #End If
  2096. Return Me.ReportVisaDeviceOperationOkay(True, synopsis, "Failed listing script {0}", name)
  2097. Else
  2098. If Me.ReportVisaDeviceOperationOkay(True, synopsis, "Failed listing script {0}", name) Then
  2099. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Failed writing to the instrument.{0}{1}.",
  2100. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  2101. End If
  2102. Return False
  2103. End If
  2104. Catch
  2105. Me.OnMessageAvailable(TraceEventType.Error, synopsis, "Failed fetching script {0}", name)
  2106. Return False
  2107. Finally
  2108. End Try
  2109. End Function
  2110. ''' <summary>
  2111. ''' Fetches the the <paramref name="value">specified</paramref> script source.
  2112. ''' </summary>
  2113. ''' <param name="name">Specifies the script name.</param>
  2114. ''' <returns></returns>
  2115. ''' <remarks></remarks>
  2116. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  2117. Public Function FetchScriptSource(ByVal nodeNumber As Integer, ByVal name As String) As Boolean
  2118. Dim synopsis As String = "Fetch Script Source"
  2119. Me._lastFetchScriptSource = ""
  2120. If String.IsNullOrEmpty(name) Then
  2121. Return False
  2122. End If
  2123. ' clear data queue and report if not empty.
  2124. Me.ClearDataQueue(nodeNumber, True)
  2125. If Me.WriteLine("isr.script.list({0},{1})", name, nodeNumber) Then
  2126. Try
  2127. ' give the instrument time to get the code.
  2128. Threading.Thread.Sleep(500)
  2129. Me._lastFetchScriptSource = MyBase.ReadLines(10, 400, True)
  2130. #If True Then
  2131. ' trap non-empty buffer.
  2132. Try
  2133. If Me.IsMessageAvailable Then
  2134. Debug.Assert(Not Debugger.IsAttached, "Buffer not empty")
  2135. End If
  2136. IsStatementTrue("node[{0}] == nil", 1)
  2137. Catch
  2138. Debug.Assert(Not Debugger.IsAttached, "Buffer not empty")
  2139. End Try
  2140. #End If
  2141. Return Me.ReportDeviceOperationOkay(nodeNumber, synopsis, "Failed listing script {0} from node {1}", name, nodeNumber)
  2142. Catch
  2143. Me.OnMessageAvailable(TraceEventType.Error, synopsis, "Failed fetching script {0}", name)
  2144. Return False
  2145. Finally
  2146. End Try
  2147. Else
  2148. If Me.ReportVisaDeviceOperationOkay(True, synopsis, "Failed fetching script {0} source from node {1}", name, nodeNumber) Then
  2149. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Failed fetching script source from node{0}.{1}{2}", nodeNumber,
  2150. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  2151. End If
  2152. Return False
  2153. End If
  2154. End Function
  2155. ''' <summary>
  2156. ''' Fetches the script source.
  2157. ''' </summary>
  2158. ''' <param name="script">Specifies the script.</param>
  2159. ''' <param name="node">Specifies the node.</param>
  2160. ''' <returns></returns>
  2161. ''' <remarks></remarks>
  2162. Public Function FetchScriptSource(ByVal script As IScriptEntity, ByVal node As INodeEntity) As Boolean
  2163. If script Is Nothing Then
  2164. Throw New ArgumentNullException("script")
  2165. End If
  2166. If node Is Nothing Then
  2167. Throw New ArgumentNullException("node")
  2168. End If
  2169. If node.IsController Then
  2170. Return FetchScriptSource(script.Name)
  2171. Else
  2172. Return FetchScriptSource(node.Number, script.Name)
  2173. End If
  2174. End Function
  2175. Private _nilifyTimeout As Integer
  2176. ''' <summary>
  2177. ''' Gets or sets the time out for nilifying a script.
  2178. ''' </summary>
  2179. Public Property NilifyTimeout() As Integer
  2180. Get
  2181. Return Me._nilifyTimeout
  2182. End Get
  2183. Set(ByVal Value As Integer)
  2184. Me._nilifyTimeout = Value
  2185. End Set
  2186. End Property
  2187. ''' <summary>
  2188. ''' Makes a script nil. Return true if the script is nil.
  2189. ''' </summary>
  2190. ''' <param name="name">Specifies the script name</param>
  2191. ''' <returns></returns>
  2192. ''' <remarks>
  2193. ''' Assumes the script is known to exist.
  2194. ''' Waits for operation completion.
  2195. ''' </remarks>
  2196. Private Function _nilifyScript(ByVal name As String) As Boolean
  2197. If String.IsNullOrEmpty(name) Then
  2198. Return False
  2199. End If
  2200. Dim synopsis As String = "Nullifying script"
  2201. Me.EnableWaitComplete()
  2202. If Me.WriteLine("{0} = nil waitcomplete()", name) Then
  2203. Me.AwaitOperationCompleted(Me._nilifyTimeout, Me._nilifyTimeout \ 10 + 10)
  2204. If Me.IsNil(name) Then
  2205. Return True
  2206. Else
  2207. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' script {1} still exists after nil.{2}{3}",
  2208. Me.ResourceName, name,
  2209. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  2210. Return False
  2211. End If
  2212. Else
  2213. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed nullifying script {1}.{2}{3}",
  2214. Me.ResourceName, name,
  2215. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  2216. Return False
  2217. End If
  2218. End Function
  2219. ''' <summary>
  2220. ''' Makes a script nil
  2221. ''' </summary>
  2222. ''' <param name="name">Specifies the script name</param>
  2223. ''' <returns></returns>
  2224. ''' <remarks></remarks>
  2225. Public Function NilifyScript(ByVal name As String) As Boolean Implements ITspInstrument.NilifyScript
  2226. If String.IsNullOrEmpty(name) Then
  2227. Return False
  2228. End If
  2229. If Me.IsNil(name) Then
  2230. Return True
  2231. Else
  2232. Return Me._nilifyScript(name)
  2233. End If
  2234. End Function
  2235. ''' <summary>
  2236. ''' Runs the named script.
  2237. ''' </summary>
  2238. ''' <param name="name">Specifies the script name.</param>
  2239. ''' <param name="timeout">Specifies the time to wait for the instrument to
  2240. ''' return operation completed.</param>
  2241. ''' <returns></returns>
  2242. ''' <remarks>
  2243. ''' Waits for operation completion.
  2244. ''' </remarks>
  2245. Public Function RunScript(ByVal name As String, ByVal timeout As Integer) As Boolean Implements ITspInstrument.RunScript
  2246. ' Check name
  2247. If String.IsNullOrEmpty(name) Then
  2248. Return False
  2249. End If
  2250. Dim returnedValue As Integer = 1
  2251. If Me.WriteLine("{0}.run() waitcomplete() print('{1}') ", name, returnedValue) Then
  2252. ' wait till we get a reply from the instrument or timeout.
  2253. Dim endTime As DateTime = DateTime.Now.Add(TimeSpan.FromMilliseconds(timeout))
  2254. Do
  2255. Threading.Thread.Sleep(50)
  2256. Loop Until endTime < DateTime.Now Or Me.IsMessageAvailable
  2257. If Me.IsMessageAvailable Then
  2258. Dim value As Integer? = Me.ReadInt32()
  2259. Return value.HasValue AndAlso value.Value = returnedValue
  2260. Else
  2261. Throw New isr.Tsp.ScriptCallException("Timeout waiting operation completion running the script '" & name & "'")
  2262. End If
  2263. Else
  2264. Return False
  2265. End If
  2266. End Function
  2267. ''' <summary>
  2268. ''' Runs the named script.
  2269. ''' </summary>
  2270. ''' <param name="nodeNumber">Specifies the subsystem node.</param>
  2271. ''' <param name="name">Specifies the script name.</param>
  2272. ''' <param name="timeout">Specifies the time to wait for the instrument to
  2273. ''' return operation completed.</param>
  2274. ''' <returns></returns>
  2275. ''' <remarks>
  2276. ''' Waits for operation completion.
  2277. ''' </remarks>
  2278. Public Function RunScript(ByVal nodeNumber As Integer, ByVal name As String, ByVal timeout As Integer) As Boolean Implements ITspInstrument.RunScript
  2279. Dim synopsis As String = "Run Script"
  2280. ' Check name
  2281. If String.IsNullOrEmpty(name) Then
  2282. Return False
  2283. End If
  2284. 'If Not Me.WriteLine("node[{1}].execute( 'script.user.scripts.{0}()' ) waitcomplete({1})", name, nodeNumber) Then
  2285. If Me.ExecuteCommandWaitComplete(nodeNumber, timeout, False, "{0}.run()", name) Then
  2286. Return True
  2287. Else
  2288. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' timed out waiting for script '{1}' on node {2}.{3}{4}",
  2289. Me.ResourceName, name, nodeNumber,
  2290. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  2291. Return False
  2292. End If
  2293. End Function
  2294. ''' <summary>
  2295. ''' Runs the script.
  2296. ''' </summary>
  2297. ''' <param name="node">Specifies the subsystem node.</param>
  2298. ''' <param name="script">Specifies the script.</param>
  2299. ''' <returns></returns>
  2300. ''' <remarks>
  2301. ''' Waits for operation completion.
  2302. ''' </remarks>
  2303. Public Function RunScript(ByVal script As IScriptEntity, ByVal node As INodeEntity) As Boolean Implements ITspInstrument.RunScript
  2304. If script Is Nothing Then
  2305. Throw New ArgumentNullException("script")
  2306. End If
  2307. If node Is Nothing Then
  2308. Throw New ArgumentNullException("node")
  2309. End If
  2310. Dim synopsis As String = "Run Script"
  2311. ' Check name
  2312. If String.IsNullOrEmpty(script.Name) Then
  2313. Return False
  2314. End If
  2315. 'If Not Me.WriteLine("node[{1}].execute( 'script.user.scripts.{0}()' ) waitcomplete({1})", name, nodeNumber) Then
  2316. If Not Me.WriteLine("node[{1}].execute( '{0}.run()' ) waitcomplete({1})", script.Name, node.Number) Then
  2317. Return False
  2318. End If
  2319. Me.IssueWaitComplete(0)
  2320. If Not Me.AwaitOperationCompleted(script.Timeout, script.Timeout \ 10 + 10) Then
  2321. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' timed out waiting for script '{1}' on node {2}.{3}{4}",
  2322. Me.ResourceName, script.Name, node.Number,
  2323. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  2324. Return False
  2325. End If
  2326. End Function
  2327. Private _saveTimeout As Integer
  2328. ''' <summary>
  2329. ''' Gets or sets the time out for saving a script.
  2330. ''' </summary>
  2331. Public Property SaveTimeout() As Integer
  2332. Get
  2333. Return Me._saveTimeout
  2334. End Get
  2335. Set(ByVal Value As Integer)
  2336. Me._saveTimeout = Value
  2337. End Set
  2338. End Property
  2339. ''' <summary>
  2340. ''' Returns true if the specified script exists as a saved script.
  2341. ''' </summary>
  2342. ''' <param name="name">Specifies the script name</param>
  2343. ''' <returns></returns>
  2344. ''' <remarks></remarks>
  2345. Public Function LastSavedScriptExists(ByVal name As String) As Boolean Implements ITspInstrument.LastSavedScriptExists
  2346. If String.IsNullOrEmpty(name) Then
  2347. Return False
  2348. End If
  2349. Return Me._lastFetchedSavedScripts.IndexOf(name & ",", 0, StringComparison.OrdinalIgnoreCase) >= 0
  2350. End Function
  2351. ''' <summary>
  2352. ''' Returns true if the specified script exists as a saved script.
  2353. ''' </summary>
  2354. ''' <param name="name">Specifies the script name</param>
  2355. ''' <param name="refreshScriptCatalog">True to refresh the list of saved scripts.</param>
  2356. ''' <returns></returns>
  2357. ''' <remarks></remarks>
  2358. Public Function SavedScriptExists(ByVal name As String, ByVal refreshScriptCatalog As Boolean) As Boolean Implements ITspInstrument.SavedScriptExists
  2359. If refreshScriptCatalog Then
  2360. Me.FetchSavedScripts()
  2361. End If
  2362. Return LastSavedScriptExists(name)
  2363. End Function
  2364. #End Region
  2365. #Region " TSP SCRIPTS: PARSE, READ, WRITE "
  2366. ''' <summary>
  2367. ''' Reads the scripts, parses them and saves them to file.
  2368. ''' </summary>
  2369. ''' <param name="filePath">Specifies the folder where scripts are stored.</param>
  2370. ''' <param name="retainOutline">Specifies if the code outline is retained or trimmed.</param>
  2371. ''' <returns></returns>
  2372. ''' <remarks></remarks>
  2373. Public Function ReadParseWriteScript(ByVal filePath As String, ByVal retainOutline As Boolean) As Boolean
  2374. Dim synopsis As String = "Read, Parse, Write Script"
  2375. Dim scriptSource As String = ""
  2376. ' check if file exists.
  2377. If isr.Core.IOExtensions.FileSize(filePath) < 2 Then
  2378. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Script file '{0}' not found.{1}{2}",
  2379. filePath,
  2380. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  2381. Return False
  2382. Else
  2383. scriptSource = TspUserScript.ReadScript(filePath)
  2384. If String.IsNullOrEmpty(scriptSource) Then
  2385. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Script file '{0}' includes no source.{1}{2}",
  2386. filePath,
  2387. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  2388. Return False
  2389. Else
  2390. scriptSource = TspUserScript.ParseScript(scriptSource, retainOutline)
  2391. If String.IsNullOrEmpty(scriptSource) Then
  2392. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Parse script '{0}' is empty.{1}{2}",
  2393. filePath,
  2394. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  2395. Return False
  2396. Else
  2397. filePath = filePath & ".debug"
  2398. If Not TspUserScript.WriteScript(scriptSource, filePath) Then
  2399. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Failed writing script to '{0}'.{1}{2}",
  2400. filePath,
  2401. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  2402. Return False
  2403. End If
  2404. End If
  2405. End If
  2406. End If
  2407. Return True
  2408. End Function
  2409. ''' <summary>
  2410. ''' Reads the scripts, parses them and saves them to file.
  2411. ''' </summary>
  2412. ''' <param name="folderPath">Specifies the folder where scripts are stored.</param>
  2413. ''' <param name="scripts">Specifies the collection of scripts.</param>
  2414. ''' <param name="retainOutline">Specifies if the code outline is retained or trimmed.</param>
  2415. ''' <returns></returns>
  2416. ''' <remarks></remarks>
  2417. Public Function ReadParseWriteScripts(ByVal folderPath As String, ByVal scripts As ScriptEntityCollection,
  2418. ByVal retainOutline As Boolean) As Boolean
  2419. If folderPath Is Nothing Then
  2420. Throw New ArgumentNullException("folderPath")
  2421. End If
  2422. If scripts Is Nothing Then
  2423. Throw New ArgumentNullException("scripts")
  2424. End If
  2425. Dim synopsis As String = "Read, Parse, Write Scripts"
  2426. Dim success As Boolean = True
  2427. If scripts IsNot Nothing AndAlso scripts.Count > 0 Then
  2428. For Each script As IScriptEntity In scripts
  2429. If script.IsModelMatch(Me._controllerNode.ModelNumber) AndAlso script.RequiresReadParseWrite Then
  2430. If String.IsNullOrEmpty(script.FileName) Then
  2431. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "File name not specified for script '{0}'.{1}{2}",
  2432. script.FileName,
  2433. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  2434. Else
  2435. Dim filePath As String = System.IO.Path.Combine(folderPath, script.FileName)
  2436. If Not Me.ReadParseWriteScript(filePath, retainOutline) Then
  2437. success = False
  2438. End If
  2439. End If
  2440. End If
  2441. Next
  2442. End If
  2443. Return success
  2444. End Function
  2445. #End Region
  2446. #Region " TSP SCRIPTS: LOAD FROM FILE "
  2447. ''' <summary>
  2448. ''' Loads a named script into the instrument.
  2449. ''' </summary>
  2450. ''' <param name="name">Specifies the script name</param>
  2451. ''' <param name="filePath">The file path.</param>
  2452. ''' <returns><c>true</c> if success, <c>false</c> otherwise</returns>
  2453. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  2454. Public Function LoadScriptFileSimple(ByVal name As String, ByVal filePath As String) As Boolean
  2455. Dim passed As Boolean
  2456. Try
  2457. Using tspFile As System.IO.StreamReader = TspUserScript.OpenScriptFile(filePath)
  2458. passed = Not tspFile Is Nothing
  2459. Dim isFirstLine As Boolean
  2460. Dim line As String
  2461. If passed Then
  2462. isFirstLine = True
  2463. Do While passed AndAlso Not tspFile.EndOfStream
  2464. line = tspFile.ReadLine.Trim
  2465. If Not String.IsNullOrEmpty(line) Then
  2466. If isFirstLine Then
  2467. passed = Me.WriteLine("loadscript " & name)
  2468. isFirstLine = False
  2469. End If
  2470. If passed Then
  2471. passed = Me.WriteLine(line)
  2472. End If
  2473. End If
  2474. Loop
  2475. If passed Then
  2476. passed = Me.WriteLine("endscript")
  2477. End If
  2478. End If
  2479. End Using
  2480. Return passed
  2481. Catch
  2482. Throw
  2483. Finally
  2484. End Try
  2485. End Function
  2486. ''' <summary>
  2487. ''' Loads a named script into the instrument allowing control over how
  2488. ''' errors and prompts are handled.
  2489. ''' For loading a script that does not includes functions, turn off errors
  2490. ''' and turn on the prompt.
  2491. ''' </summary>
  2492. ''' <param name="name">Specifies the script name</param>
  2493. ''' <param name="filePath">Specifies the script file name</param>
  2494. ''' <param name="retainOutline">Specifies if the code outline is retained or trimmed.</param>
  2495. ''' <returns></returns>
  2496. ''' <remarks></remarks>
  2497. <System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Maintainability", "CA1502:AvoidExcessiveComplexity")>
  2498. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  2499. Public Function LoadScriptFileLegacy(ByVal name As String, ByVal filePath As String, ByVal retainOutline As Boolean) As Boolean
  2500. Dim chunkLine As String
  2501. Dim commandLine As String
  2502. Try
  2503. Using tspFile As System.IO.StreamReader = TspUserScript.OpenScriptFile(filePath)
  2504. If tspFile Is Nothing Then
  2505. ' now report the error to the calling module
  2506. Throw New BaseException("Failed opening TSP Script File '" & filePath & "'.")
  2507. End If
  2508. Using debugFile As System.IO.StreamWriter = New System.IO.StreamWriter(filePath & ".debug")
  2509. Dim deviceErrors As String = String.Empty
  2510. Dim isInCommentBlock As Boolean
  2511. isInCommentBlock = False
  2512. Dim lineNumber As Integer
  2513. lineNumber = 0
  2514. Dim isFirstLine As Boolean
  2515. isFirstLine = True
  2516. Dim wasInCommentBlock As Boolean
  2517. Dim lineType As isr.Tsp.TspChunkLineContentType
  2518. Do While Not tspFile.EndOfStream
  2519. chunkLine = tspFile.ReadLine()
  2520. chunkLine = TspUserScript.TrimTspChuckLine(chunkLine, retainOutline)
  2521. lineNumber = lineNumber + 1
  2522. wasInCommentBlock = isInCommentBlock
  2523. lineType = TspUserScript.ParseTspChuckLine(chunkLine, isInCommentBlock)
  2524. If lineType = TspChunkLineContentType.None Then
  2525. ' if no data, nothing to do.
  2526. ElseIf wasInCommentBlock Then
  2527. ' if was in a comment block exit the comment block if
  2528. ' received a end of comment block
  2529. If lineType = isr.Tsp.TspChunkLineContentType.EndCommentBlock Then
  2530. isInCommentBlock = False
  2531. End If
  2532. ElseIf lineType = TspChunkLineContentType.StartCommentBlock Then
  2533. isInCommentBlock = True
  2534. ElseIf lineType = TspChunkLineContentType.Comment Then
  2535. ' if comment line do nothing
  2536. ElseIf lineType = TspChunkLineContentType.Syntax OrElse lineType = TspChunkLineContentType.SyntaxStartCommentBlock Then
  2537. If lineType = TspChunkLineContentType.SyntaxStartCommentBlock Then
  2538. chunkLine = chunkLine.Substring(0, chunkLine.IndexOf(TspSyntax.StartCommentChunk, StringComparison.OrdinalIgnoreCase))
  2539. End If
  2540. ' end each line with a space
  2541. chunkLine &= " "
  2542. If isFirstLine Then
  2543. ' issue a start of script command. The command
  2544. ' 'loadscript' identifies the beginning of the named script.
  2545. commandLine = "loadscript " & name & " "
  2546. If Me.WriteLine(commandLine) Then
  2547. isFirstLine = False
  2548. Else
  2549. ' now report the error to the calling module
  2550. If Me.HandleInstrumentErrorIfError(True) Then
  2551. deviceErrors = Me.DeviceErrors
  2552. End If
  2553. Dim messageFormat As String = "{0} failed sending a 'loadscript' for script '{1}' from file '{2}'"
  2554. Throw New ScriptLoadingException(messageFormat, Me.ResourceName, name, filePath, deviceErrors)
  2555. End If
  2556. End If
  2557. If Me.WriteLine(chunkLine) Then
  2558. ' increment debug line number
  2559. debugFile.WriteLine(chunkLine)
  2560. Else
  2561. ' now report the error to the calling module
  2562. If Me.HandleInstrumentErrorIfError(True) Then
  2563. deviceErrors = Me.DeviceErrors
  2564. End If
  2565. Dim messageFormat As String = "{0} failed sending failed sending a syntax line: {4}{1}{4} for script '{2}' from file '{3}'"
  2566. Throw New ScriptLoadingException(messageFormat, Me.ResourceName, chunkLine, name, filePath, deviceErrors)
  2567. End If
  2568. If lineType = TspChunkLineContentType.SyntaxStartCommentBlock Then
  2569. isInCommentBlock = True
  2570. End If
  2571. End If
  2572. Loop
  2573. End Using
  2574. End Using
  2575. ' Tell TSP complete script has been downloaded.
  2576. commandLine = "endscript waitcomplete() print('1') "
  2577. ' now report the error to the calling module
  2578. If Not Me.ReportVisaDeviceOperationOkay(Not Me.WriteLine(commandLine),
  2579. "Failed Loading Script",
  2580. "{0} failed sending an 'endscript' for script '{1}' from file '{2}'", Me.ResourceName, name, filePath) Then
  2581. Return False
  2582. End If
  2583. ' wait till we get a reply from the instrument or timeout.
  2584. ' The command above does not seem to work! It looks like the print does not get executed!
  2585. Dim endTime As DateTime = DateTime.Now.Add(TimeSpan.FromMilliseconds(3000))
  2586. Dim value As String = String.Empty
  2587. Do
  2588. Do
  2589. Threading.Thread.Sleep(50)
  2590. Loop Until endTime < DateTime.Now Or Me.IsMessageAvailable
  2591. If Me.IsMessageAvailable Then
  2592. value = Me.ReadLine
  2593. End If
  2594. Loop Until endTime < DateTime.Now Or value.StartsWith("1", StringComparison.OrdinalIgnoreCase)
  2595. If endTime < DateTime.Now Then
  2596. 'Throw New isr.Tsp.ScriptCallException("Timeout waiting operation completion loading the script '" & Me._name & "'")
  2597. End If
  2598. ' add a wait to ensure the system returns the last status.
  2599. Threading.Thread.Sleep(100)
  2600. ' flush the receive buffer until empty.
  2601. Me._discardUnreadData(True)
  2602. Return True
  2603. Catch
  2604. ' flush the receive buffer until empty.
  2605. Me._discardUnreadData(True)
  2606. Throw
  2607. Finally
  2608. End Try
  2609. End Function
  2610. ''' <summary>
  2611. ''' Loads the specified TSP script from file.
  2612. ''' </summary>
  2613. ''' <param name="folderPath">Specifies the script folder path</param>
  2614. ''' <param name="script">Specifies reference to a valid <see cref="ScriptEntity">script</see></param>
  2615. ''' <returns>Returns True if ok.</returns>
  2616. ''' <remarks></remarks>
  2617. Public Function LoadUserScriptFile(ByVal folderPath As String, ByVal script As IScriptEntity) As Boolean
  2618. If folderPath Is Nothing Then
  2619. Throw New ArgumentNullException("folderPath")
  2620. End If
  2621. If script Is Nothing Then
  2622. Throw New ArgumentNullException("script")
  2623. End If
  2624. Dim synopsis As String = "Load Custom Firmware"
  2625. If Not Me.IsNil(script.Name) Then
  2626. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis, "Instrument '{0}' script {1} already exists.", Me.ResourceName, script.Name)
  2627. Return True
  2628. End If
  2629. Dim filePath As String = System.IO.Path.Combine(folderPath, script.FileName)
  2630. ' check if file exists.
  2631. If isr.Core.IOExtensions.FileSize(filePath) < 2 Then
  2632. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Script file '{0}' not found.{1}{2}",
  2633. filePath,
  2634. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  2635. Return False
  2636. End If
  2637. Me.DisplayLine(2, "Loading {0} from file", script.Name)
  2638. If Not Me.LoadScriptFileLegacy(script.Name, filePath, True) Then
  2639. Me.DisplayLine(2, "Failed loading {0} from file", script.Name)
  2640. If Me.ReportVisaDeviceOperationOkay(False, synopsis, "loading {0} from {1}", script.Name, filePath) Then
  2641. ' report failure if not an instrument or VISA error (handler returns Okay.)
  2642. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed loading {1} from {2}.{3}{4}",
  2643. Me.ResourceName, script.Name, filePath,
  2644. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  2645. End If
  2646. Return False
  2647. End If
  2648. ' do a garbage collection
  2649. Me.CollectGarbageWaitComplete(script.Timeout, synopsis, "collecting garbage. Error ignored")
  2650. Me.OnMessageAvailable(TraceEventType.Information, synopsis, "Instrument '{0}' {1} script loaded.", Me.ResourceName, script.Name)
  2651. Me.DisplayLine(2, "Done loading {0} from file", script.Name)
  2652. Return True
  2653. End Function
  2654. #End Region
  2655. #Region " TSP SCRIPTS: LOAD "
  2656. ''' <summary>
  2657. ''' Load the code. Code could be embedded as a comma separated string table format, in
  2658. ''' which case the script should be concatenated first.
  2659. ''' </summary>
  2660. ''' <param name="value">Includes the script as a long string.</param>
  2661. ''' <returns></returns>
  2662. ''' <remarks></remarks>
  2663. Public Function LoadString(ByVal value As String) As Boolean Implements ITspInstrument.LoadString
  2664. If value Is Nothing Then
  2665. Throw New ArgumentNullException("value")
  2666. End If
  2667. Dim scriptLines As String() = value.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
  2668. Return LoadString(scriptLines)
  2669. End Function
  2670. ''' <summary>
  2671. ''' Load the code. Code could be embedded as a comma separated string table format, in
  2672. ''' which case the script should be concatenated first.
  2673. ''' </summary>
  2674. ''' <param name="scriptLines">Includes the script in lines.</param>
  2675. ''' <returns></returns>
  2676. ''' <remarks></remarks>
  2677. Public Function LoadString(ByVal scriptLines() As String) As Boolean Implements ITspInstrument.LoadString
  2678. If scriptLines Is Nothing Then
  2679. Throw New ArgumentNullException("scriptLines")
  2680. End If
  2681. If scriptLines IsNot Nothing Then
  2682. For Each scriptLine As String In scriptLines
  2683. scriptLine = scriptLine.Trim
  2684. If Not String.IsNullOrEmpty(scriptLine) Then
  2685. If Not Me.WriteLine(scriptLine) Then
  2686. Return False
  2687. End If
  2688. End If
  2689. Next
  2690. End If
  2691. Return True
  2692. End Function
  2693. ''' <summary>
  2694. ''' Load the script embedded in the string.
  2695. ''' </summary>
  2696. ''' <param name="scriptLines">Contains the script code line by line</param>
  2697. ''' <returns></returns>
  2698. ''' <remarks></remarks>
  2699. Public Function LoadScript(ByVal name As String, ByVal scriptLines() As String) As Boolean Implements ITspInstrument.LoadScript
  2700. If scriptLines Is Nothing Then
  2701. Throw New ArgumentNullException("scriptLines")
  2702. End If
  2703. Dim synopsis As String = "Load Script"
  2704. Try
  2705. Dim firstLine As String = scriptLines(0)
  2706. ' check if we already have the load/end constructs.
  2707. If firstLine.Contains(name) OrElse firstLine.Contains("loadscript") Then
  2708. Return Me.LoadString(scriptLines)
  2709. Else
  2710. If Me.WriteLine("loadscript " & name) Then
  2711. If Me.LoadString(scriptLines) Then
  2712. If Me.WriteLine("endscript waitcomplete()") Then
  2713. Return Me.ReportVisaDeviceOperationOkay(True, synopsis, "loading script")
  2714. Else
  2715. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed loading script '{1}'.{2}{3}",
  2716. Me.ResourceName, name,
  2717. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  2718. Return False
  2719. End If
  2720. Else
  2721. Return False
  2722. End If
  2723. Else
  2724. Return False
  2725. End If
  2726. End If
  2727. Catch
  2728. Throw
  2729. End Try
  2730. End Function
  2731. ''' <summary>
  2732. ''' Load the script embedded in the string.
  2733. ''' </summary>
  2734. ''' <param name="name">Contains the script name</param>
  2735. ''' <param name="source">Contains the script code line by line</param>
  2736. ''' <returns></returns>
  2737. ''' <remarks></remarks>
  2738. Public Function LoadScript(ByVal name As String, ByVal source As String) As Boolean
  2739. If name Is Nothing Then
  2740. Throw New ArgumentNullException("name")
  2741. End If
  2742. If source Is Nothing Then
  2743. Throw New ArgumentNullException("source")
  2744. End If
  2745. If source.Substring(0, 50).Trim.StartsWith("{", True, Globalization.CultureInfo.CurrentCulture) Then
  2746. source = "loadstring(table.concat(" & source & "))() "
  2747. End If
  2748. Dim scriptLines() As String = source.Split(Environment.NewLine.ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
  2749. Return Me.LoadScript(name, scriptLines)
  2750. End Function
  2751. ''' <summary>
  2752. ''' Load an anonymous script embedded in the string.
  2753. ''' </summary>
  2754. ''' <param name="source">Contains the script code line by line</param>
  2755. ''' <returns></returns>
  2756. ''' <remarks></remarks>
  2757. Public Function LoadScript(ByVal source As String) As Boolean
  2758. If source Is Nothing Then
  2759. Throw New ArgumentNullException("source")
  2760. End If
  2761. If source.Substring(0, 50).Trim.StartsWith("{", True, Globalization.CultureInfo.CurrentCulture) Then
  2762. source = "loadstring(table.concat(" & source & "))() "
  2763. End If
  2764. Return Me.LoadString(source)
  2765. End Function
  2766. #End Region
  2767. #Region " TSP: STATUS "
  2768. Public Overrides Property OperationEventEnable(ByVal access As Visa.ResourceAccessLevels) As Integer
  2769. Get
  2770. Return MyBase.OperationEventEnable(access)
  2771. End Get
  2772. Set(ByVal value As Integer)
  2773. MyBase.OperationEventEnable(access) = value
  2774. If (value And OperationEventBits.UserRegister) <> 0 Then
  2775. ' if enabling the user register, enable all events on the user register.
  2776. Me.WriteLine("status.operation.user.enable = {0}", &H4FFF)
  2777. End If
  2778. End Set
  2779. End Property
  2780. #End Region
  2781. #Region " TSPX: EXTENDED FUNCTIONS WITH ERROR MANAGEMENT "
  2782. ''' <summary>
  2783. ''' Do garbage collection. Reports operations synopsis.
  2784. ''' </summary>
  2785. ''' <returns></returns>
  2786. ''' <remarks></remarks>
  2787. Public Function CollectGarbageWaitComplete(ByVal timeout As Integer, ByVal synopsis As String, ByVal format As String, ByVal ParamArray args() As Object) As Boolean
  2788. If Me.CollectGarbage() Then
  2789. IssueWaitComplete(0)
  2790. Me.AwaitOperationCompleted(timeout, timeout \ 10 + 10)
  2791. Return Me.ReportVisaDeviceOperationOkay(False, synopsis, format, args)
  2792. Else
  2793. Me.ReportVisaDeviceOperationOkay(True, synopsis, synopsis, format, args)
  2794. Return False
  2795. End If
  2796. End Function
  2797. ''' <summary>
  2798. ''' Do garbage collection. Reports operations synopsis.
  2799. ''' </summary>
  2800. ''' <returns></returns>
  2801. ''' <remarks></remarks>
  2802. Public Function CollectGarbageWaitComplete(ByVal nodeNumber As Integer, ByVal timeout As Integer, ByVal synopsis As String, ByVal format As String, ByVal ParamArray args() As Object) As Boolean
  2803. If Me.CollectGarbage(nodeNumber) Then
  2804. IssueWaitComplete(nodeNumber)
  2805. Me.AwaitOperationCompleted(timeout, timeout \ 10 + 10)
  2806. Return Me.ReportDeviceOperationOkay(nodeNumber, synopsis, format, args)
  2807. Else
  2808. Me.ReportDeviceOperationOkay(nodeNumber, synopsis, format, args)
  2809. Return False
  2810. End If
  2811. End Function
  2812. ''' <summary>
  2813. ''' Do garbage collection. Reports operations synopsis.
  2814. ''' </summary>
  2815. ''' <returns></returns>
  2816. ''' <remarks></remarks>
  2817. Public Function CollectGarbageWaitComplete(ByVal node As INodeEntity, ByVal timeout As Integer, ByVal synopsis As String, ByVal format As String, ByVal ParamArray args() As Object) As Boolean
  2818. If node Is Nothing Then
  2819. Throw New ArgumentNullException("node")
  2820. End If
  2821. If node.IsController Then
  2822. Return CollectGarbageWaitComplete(timeout, synopsis, format, args)
  2823. Else
  2824. Return CollectGarbageWaitComplete(node.Number, timeout, synopsis, format, args)
  2825. End If
  2826. End Function
  2827. #End Region
  2828. #Region " TSPX: SCRIPT COLLECTION - LEGACY "
  2829. Private _legacyScripts As ScriptEntityCollection
  2830. ''' <summary>
  2831. ''' Gets the list of legacy scripts.
  2832. ''' </summary>
  2833. ''' <returns></returns>
  2834. ''' <remarks></remarks>
  2835. Public Function LegacyScripts() As ScriptEntityCollection Implements ITspInstrument.LegacyScripts
  2836. Return Me._legacyScripts
  2837. End Function
  2838. ''' <summary>
  2839. ''' Adds a new script to the list of legacy scripts.
  2840. ''' </summary>
  2841. ''' <param name="name"></param>
  2842. ''' <returns></returns>
  2843. ''' <remarks></remarks>
  2844. Public Function AddLegacyScript(ByVal name As String) As IScriptEntity Implements ITspInstrument.AddLegacyScript
  2845. Dim script As New ScriptEntity(name, "")
  2846. Me._legacyScripts.Add(script)
  2847. Return script
  2848. End Function
  2849. ''' <summary>
  2850. ''' Create a new instance of the legacy scripts
  2851. ''' </summary>
  2852. ''' <remarks></remarks>
  2853. Public Sub NewLegacyScripts() Implements ITspInstrument.NewLegacyScripts
  2854. Me._legacyScripts = New ScriptEntityCollection
  2855. End Sub
  2856. #End Region
  2857. #Region " TSPX: SCRIPT COLLECTION "
  2858. Private _scripts As ScriptEntityCollection
  2859. ''' <summary>
  2860. ''' Gets the list of scripts.
  2861. ''' </summary>
  2862. ''' <returns></returns>
  2863. ''' <remarks></remarks>
  2864. Public Function Scripts() As ScriptEntityCollection Implements ITspInstrument.Scripts
  2865. Return Me._scripts
  2866. End Function
  2867. ''' <summary>
  2868. ''' Adds a new script to the list of scripts.
  2869. ''' </summary>
  2870. ''' <param name="name">Specifies the name of the script</param>
  2871. ''' <param name="modelMask">Specifies the family of instrument models for this script.</param>
  2872. ''' <returns></returns>
  2873. ''' <remarks></remarks>
  2874. Public Function AddScript(ByVal name As String, ByVal modelMask As String) As IScriptEntity Implements ITspInstrument.AddScript
  2875. Dim script As New ScriptEntity(name, modelMask)
  2876. Me._scripts.Add(script)
  2877. Return script
  2878. End Function
  2879. ''' <summary>
  2880. ''' Create a new instance of the scripts
  2881. ''' </summary>
  2882. ''' <remarks></remarks>
  2883. Public Sub NewScripts() Implements ITspInstrument.NewScripts
  2884. Me._scripts = New ScriptEntityCollection()
  2885. End Sub
  2886. #End Region
  2887. #Region " TSPX: SCRIPTS "
  2888. ''' <summary>
  2889. ''' Checks and returns true if all scripts are loaded on the specified node.
  2890. ''' </summary>
  2891. ''' <param name="scripts">Specifies the collection of scripts.</param>
  2892. ''' <param name="node">Specifies the node.</param>
  2893. ''' <returns></returns>
  2894. ''' <remarks></remarks>
  2895. Public Function AllUserScriptsExist(ByVal scripts As ScriptEntityCollection, ByVal node As INodeEntity) As Boolean
  2896. If scripts Is Nothing Then
  2897. Throw New ArgumentNullException("scripts")
  2898. End If
  2899. If node Is Nothing Then
  2900. Throw New ArgumentNullException("node")
  2901. End If
  2902. If scripts IsNot Nothing AndAlso scripts.Count > 0 Then
  2903. For Each script As IScriptEntity In scripts
  2904. ' return false if any script is not loaded.
  2905. If script.IsModelMatch(node.ModelNumber) AndAlso Not Me.IsNil(node, script.Name) Then
  2906. Return False
  2907. End If
  2908. Next
  2909. Else
  2910. Return False
  2911. End If
  2912. Return True
  2913. End Function
  2914. ''' <summary>
  2915. ''' Checks and returns true if all scripts were executed.
  2916. ''' </summary>
  2917. ''' <param name="scripts">Specifies the collection of scripts.</param>
  2918. ''' <param name="node">Specifies the node.</param>
  2919. ''' <returns></returns>
  2920. ''' <remarks></remarks>
  2921. Public Function AllUserScriptsExecuted(ByVal scripts As ScriptEntityCollection, ByVal node As INodeEntity) As Boolean
  2922. If scripts Is Nothing Then
  2923. Throw New ArgumentNullException("scripts")
  2924. End If
  2925. If node Is Nothing Then
  2926. Throw New ArgumentNullException("node")
  2927. End If
  2928. If scripts IsNot Nothing AndAlso scripts.Count > 0 Then
  2929. For Each script As IScriptEntity In scripts
  2930. ' return false if any script is not loaded.
  2931. If script.IsModelMatch(node.ModelNumber) AndAlso
  2932. script.Namespaces IsNot Nothing AndAlso script.Namespaces.Length > 0 AndAlso Me.IsNil(node, script.Namespaces) Then
  2933. Return False
  2934. End If
  2935. Next
  2936. Else
  2937. Return False
  2938. End If
  2939. Return True
  2940. End Function
  2941. ''' <summary>
  2942. ''' Checks and returns true if all scripts are loaded.
  2943. ''' </summary>
  2944. ''' <param name="scripts">Specifies the collection of scripts.</param>
  2945. ''' <param name="node">Specifies the node.</param>
  2946. ''' <returns></returns>
  2947. ''' <remarks></remarks>
  2948. Public Function AllUserScriptsSaved(ByVal scripts As ScriptEntityCollection, ByVal node As INodeEntity) As Boolean
  2949. If scripts Is Nothing Then
  2950. Throw New ArgumentNullException("scripts")
  2951. End If
  2952. If node Is Nothing Then
  2953. Throw New ArgumentNullException("node")
  2954. End If
  2955. If scripts IsNot Nothing AndAlso scripts.Count > 0 Then
  2956. If Not Me.FetchSavedScripts(node) Then
  2957. Me.OnMessageAvailable(TraceEventType.Warning, "All User Scripts Saved", "Instrument '{0}' node {1} failed fetching catalog of saved scripts.{2}{3}",
  2958. Me.ResourceName, node.Number,
  2959. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  2960. Return False
  2961. End If
  2962. For Each script As IScriptEntity In scripts
  2963. ' return false if any script is not saved.
  2964. If script.IsModelMatch(node.ModelNumber) AndAlso Not Me.SavedScriptExists(script.Name, node, False) Then
  2965. Return False
  2966. End If
  2967. Next
  2968. Else
  2969. Return False
  2970. End If
  2971. Return True
  2972. End Function
  2973. ''' <summary>
  2974. ''' Returns true if any of the specified scripts exists.
  2975. ''' </summary>
  2976. ''' <param name="scripts">Specifies the collection of scripts.</param>
  2977. ''' <param name="node">Specifies the node.</param>
  2978. ''' <returns></returns>
  2979. ''' <remarks></remarks>
  2980. Public Function AnyUserScriptExists(ByVal scripts As ScriptEntityCollection, ByVal node As INodeEntity) As Boolean
  2981. If scripts Is Nothing Then
  2982. Throw New ArgumentNullException("scripts")
  2983. End If
  2984. If node Is Nothing Then
  2985. Throw New ArgumentNullException("node")
  2986. End If
  2987. If scripts IsNot Nothing AndAlso scripts.Count > 0 Then
  2988. For Each script As IScriptEntity In scripts
  2989. If Not String.IsNullOrEmpty(script.Name) Then
  2990. If script.IsModelMatch(node.ModelNumber) AndAlso Not Me.IsNil(node, script.Name) Then
  2991. Return True
  2992. End If
  2993. End If
  2994. Next
  2995. End If
  2996. Return False
  2997. End Function
  2998. #End Region
  2999. #Region " TSPX: SCRIPTS FIRMWARE "
  3000. ''' <summary>
  3001. ''' Returns the released main firmware version.
  3002. ''' </summary>
  3003. ''' <returns></returns>
  3004. ''' <remarks></remarks>
  3005. Public Function FirmwareReleasedVersionGetter() As String
  3006. If Me._controllerNode Is Nothing Then
  3007. Return Me._scripts.Item(0).ReleasedFirmwareVersion
  3008. Else
  3009. Return FirmwareReleasedVersionGetter(Me._controllerNode)
  3010. End If
  3011. End Function
  3012. ''' <summary>
  3013. ''' Returns the released main firmware version.
  3014. ''' </summary>
  3015. ''' <param name="node">Specifies the node.</param>
  3016. ''' <returns></returns>
  3017. ''' <remarks></remarks>
  3018. Public Function FirmwareReleasedVersionGetter(ByVal node As INodeEntity) As String
  3019. If Me._controllerNode Is Nothing Then
  3020. Return Me._scripts.Item(0).ReleasedFirmwareVersion
  3021. Else
  3022. If node Is Nothing Then
  3023. Throw New ArgumentNullException("node")
  3024. End If
  3025. Return Me._scripts.SerialNumberScript(node).ReleasedFirmwareVersion
  3026. End If
  3027. End Function
  3028. ''' <summary>
  3029. ''' Returns the embedded main firmware version.
  3030. ''' </summary>
  3031. ''' <param name="node">Specifies the node.</param>
  3032. ''' <returns></returns>
  3033. ''' <remarks></remarks>
  3034. Public Function FirmwareVersionGetter(ByVal node As INodeEntity) As String
  3035. If node Is Nothing Then
  3036. Throw New ArgumentNullException("node")
  3037. End If
  3038. Return Me._scripts.SerialNumberScript(node).EmbeddedFirmwareVersion
  3039. End Function
  3040. ''' <summary>
  3041. ''' Returns the main firmware name from the controller node.
  3042. ''' </summary>
  3043. ''' <returns></returns>
  3044. ''' <remarks></remarks>
  3045. Public Function FirmwareNameGetter() As String
  3046. Return FirmwareNameGetter(Me._controllerNode)
  3047. End Function
  3048. ''' <summary>
  3049. ''' Returns the main firmware name.
  3050. ''' </summary>
  3051. ''' <param name="node">Specifies the node.</param>
  3052. ''' <returns></returns>
  3053. ''' <remarks></remarks>
  3054. Public Function FirmwareNameGetter(ByVal node As INodeEntity) As String
  3055. If node Is Nothing Then
  3056. Throw New ArgumentNullException("node")
  3057. End If
  3058. Return Me._scripts.SerialNumberScript(node).Name
  3059. End Function
  3060. Private _firmwareExists As Boolean?
  3061. ''' <summary>
  3062. ''' Returns the existence status of the main firmware on the controller node.
  3063. ''' </summary>
  3064. ''' <returns></returns>
  3065. ''' <remarks></remarks>
  3066. Public Function FirmwareExists() As Boolean
  3067. Return FirmwareExists(Me._controllerNode)
  3068. End Function
  3069. ''' <summary>
  3070. ''' Returns the existence status of the main firmware.
  3071. ''' </summary>
  3072. ''' <param name="node">Specifies the node.</param>
  3073. ''' <returns></returns>
  3074. ''' <remarks></remarks>
  3075. Public Function FirmwareExists(ByVal node As INodeEntity) As Boolean
  3076. If node Is Nothing Then
  3077. Throw New ArgumentNullException("node")
  3078. End If
  3079. If Me._firmwareExists Is Nothing OrElse Not Me._firmwareExists.HasValue Then
  3080. Me._firmwareExists = Not Me.IsNil(Me.FirmwareNameGetter(node))
  3081. End If
  3082. Return Me._firmwareExists.Value
  3083. End Function
  3084. ''' <summary>
  3085. ''' Reads and returns the local node number.
  3086. ''' </summary>
  3087. ''' <returns></returns>
  3088. ''' <remarks></remarks>
  3089. Public Function LocalNodeNumber() As Integer
  3090. Return CInt(Me.QueryPrintFormat("%d", "_G.tsplink.node"))
  3091. End Function
  3092. ''' <summary>
  3093. ''' Reads and returns the instrument serial number
  3094. ''' </summary>
  3095. ''' <returns></returns>
  3096. ''' <remarks></remarks>
  3097. Public Function SerialNumberReading() As String
  3098. Return Me.QueryPrintFormat("%d", "_G.localnode.serialno").Trim
  3099. End Function
  3100. ''' <summary>
  3101. ''' Returns the Support firmware name.
  3102. ''' </summary>
  3103. ''' <param name="node">Specifies the node.</param>
  3104. ''' <returns></returns>
  3105. ''' <remarks></remarks>
  3106. Public Function SupportFirmwareNameGetter(ByVal node As INodeEntity) As String
  3107. If node Is Nothing Then
  3108. Throw New ArgumentNullException("node")
  3109. End If
  3110. Return Me._scripts.SupportScript(node).Name
  3111. End Function
  3112. Private _supportfirmwareExists As Boolean?
  3113. ''' <summary>
  3114. ''' Returns the existence status of the Support firmware on the controller node.
  3115. ''' </summary>
  3116. ''' <returns></returns>
  3117. ''' <remarks></remarks>
  3118. Public Function SupportFirmwareExists() As Boolean
  3119. Return SupportFirmwareExists(Me._controllerNode)
  3120. End Function
  3121. ''' <summary>
  3122. ''' Returns the existence status of the Support firmware.
  3123. ''' </summary>
  3124. ''' <param name="node">Specifies the node.</param>
  3125. ''' <returns></returns>
  3126. ''' <remarks></remarks>
  3127. Public Function SupportFirmwareExists(ByVal node As INodeEntity) As Boolean
  3128. If node Is Nothing Then
  3129. Throw New ArgumentNullException("node")
  3130. End If
  3131. If Me._supportfirmwareExists Is Nothing OrElse Not Me._supportfirmwareExists.HasValue Then
  3132. Me._supportfirmwareExists = Not Me.IsNil(SupportFirmwareNameGetter(node))
  3133. End If
  3134. Return Me._supportfirmwareExists.Value
  3135. End Function
  3136. ''' <summary>
  3137. ''' Reads the firmware versions of the controller node.
  3138. ''' </summary>
  3139. ''' <param name="node">Specifies the node.</param>
  3140. ''' <returns></returns>
  3141. ''' <remarks></remarks>
  3142. Public Function ReadFirmwareVersions(ByVal node As INodeEntity) As Boolean
  3143. If node Is Nothing Then
  3144. Throw New ArgumentNullException("node")
  3145. End If
  3146. Return Me._scripts.ReadFirmwareVersions(node, Me)
  3147. End Function
  3148. ''' <summary>
  3149. ''' Returns true if all scripts were saved.
  3150. ''' </summary>
  3151. ''' <param name="node">Specifies the node.</param>
  3152. ''' <value></value>
  3153. ''' <param name="refreshScriptCatalog">Specifies the condition for updating the catalog of saved scripts before
  3154. ''' checking the status of these scripts.</param>
  3155. ''' <returns></returns>
  3156. ''' <remarks></remarks>
  3157. Public ReadOnly Property AllScriptsSaved(ByVal refreshScriptCatalog As Boolean, ByVal node As INodeEntity) As Boolean
  3158. Get
  3159. If node IsNot Nothing Then
  3160. Return Me._scripts.FindSavedScripts(node, Me, refreshScriptCatalog)
  3161. End If
  3162. End Get
  3163. End Property
  3164. ''' <summary>
  3165. ''' Returns true if all scripts exist.
  3166. ''' </summary>
  3167. ''' <param name="node">Specifies the node.</param>
  3168. ''' <value></value>
  3169. ''' <returns></returns>
  3170. ''' <remarks></remarks>
  3171. Public ReadOnly Property AllScriptsExist(ByVal node As INodeEntity) As Boolean
  3172. Get
  3173. If node IsNot Nothing Then
  3174. Return Me._scripts.FindScripts(node, Me)
  3175. End If
  3176. End Get
  3177. End Property
  3178. ''' <summary>
  3179. ''' Returns true if any script exists on the controller node.
  3180. ''' </summary>
  3181. ''' <value></value>
  3182. ''' <returns></returns>
  3183. ''' <remarks></remarks>
  3184. Public ReadOnly Property AnyScriptExists() As Boolean
  3185. Get
  3186. Return AnyScriptExists(Me.ControllerNode)
  3187. End Get
  3188. End Property
  3189. ''' <summary>
  3190. ''' Returns true if any script exists.
  3191. ''' </summary>
  3192. ''' <param name="node">Specifies the node.</param>
  3193. ''' <value></value>
  3194. ''' <returns></returns>
  3195. ''' <remarks></remarks>
  3196. Public ReadOnly Property AnyScriptExists(ByVal node As INodeEntity) As Boolean
  3197. Get
  3198. If node IsNot Nothing Then
  3199. Return Me._scripts.FindAnyScript(node, Me)
  3200. End If
  3201. End Get
  3202. End Property
  3203. ''' <summary>
  3204. ''' Returns true if any legacy scripts exist on the controller node.
  3205. ''' </summary>
  3206. ''' <value></value>
  3207. ''' <returns></returns>
  3208. ''' <remarks></remarks>
  3209. Public ReadOnly Property AnyLegacyScriptExists() As Boolean
  3210. Get
  3211. Return AnyLegacyScriptExists(Me.ControllerNode)
  3212. End Get
  3213. End Property
  3214. ''' <summary>
  3215. ''' Returns true if any legacy scripts exist.
  3216. ''' </summary>
  3217. ''' <param name="node">Specifies the node.</param>
  3218. ''' <value></value>
  3219. ''' <returns></returns>
  3220. ''' <remarks></remarks>
  3221. Public ReadOnly Property AnyLegacyScriptExists(ByVal node As INodeEntity) As Boolean
  3222. Get
  3223. If node IsNot Nothing Then
  3224. Return Me._legacyScripts.FindAnyScript(node, Me)
  3225. End If
  3226. End Get
  3227. End Property
  3228. #End Region
  3229. #Region " TSPX: DELETE SCRIPTS "
  3230. ''' <summary>
  3231. ''' Check the script version and determines if the script needs to be deleted.
  3232. ''' </summary>
  3233. ''' <param name="script">Specifies the <see cref="IScriptEntity">script</see>to delete</param>
  3234. ''' <param name="node">Specifies the system node</param>
  3235. ''' <returns>
  3236. ''' Returns true if script was deleted or did not exit. Returns false if a
  3237. ''' VISA error was encountered. Assumes that the list of saved scripts is current.
  3238. ''' </returns>
  3239. ''' <remarks></remarks>
  3240. Public Function IsDeleteUserScriptRequired(ByVal script As IScriptEntity,
  3241. ByVal node As INodeEntity,
  3242. ByVal allowDeletingNewerScripts As Boolean) As Boolean
  3243. If script Is Nothing Then
  3244. Throw New ArgumentNullException("script")
  3245. End If
  3246. If node Is Nothing Then
  3247. Throw New ArgumentNullException("node")
  3248. End If
  3249. Dim synopsis As String = "Is script deletion required"
  3250. If Me.IsNil(node, script.Name) Then
  3251. ' ignore error if nil
  3252. If ReportDeviceOperationOkay(node.Number, synopsis, "looking for script '{0}'. Ignoring error.", script.Name) Then
  3253. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis,
  3254. "Instrument '{0}' script {1} not found on node. Nothing to do.", Me.ResourceName, script.Name, node.Number)
  3255. End If
  3256. ' return false, script does not exists.
  3257. Return False
  3258. ' check if can read version
  3259. ElseIf Me.IsNil(node, script.Namespaces) Then
  3260. ' reading version requires an intact namespace. A missing name space may be missing, this might
  3261. ' indicate that referenced scripts were deleted or failed loading so this script should be deleted.
  3262. Me.OnMessageAvailable(TraceEventType.Information, synopsis,
  3263. "Instrument '{0}' some namespaces '{1}' on node {2} are nil -- script '{3}' will be deleted.",
  3264. Me.ResourceName, script.Namespaces, node.Number, script.Name)
  3265. Return True
  3266. ElseIf Not script.FirmwareVersionDefined(node, Me) Then
  3267. ' reading version requires a supported version function. Delete if a firmware version function is not
  3268. ' defined.
  3269. Me.OnMessageAvailable(TraceEventType.Information, synopsis,
  3270. "Instrument '{0}' firmware version function not defined -- script '{1}' will be deleted.",
  3271. Me.ResourceName, script.Name)
  3272. Return True
  3273. End If
  3274. ' read the script firmware version
  3275. script.ReadFirmwareVersion(node, Me)
  3276. Dim validation As FirmwareVersionStatus = script.ValidateFirmware()
  3277. Select Case validation
  3278. Case FirmwareVersionStatus.None
  3279. Me.OnMessageAvailable(TraceEventType.Information, synopsis,
  3280. "Instrument '{0}' '{1}' script firmware version on node {2} is irrelevant -- Script will be deleted.",
  3281. Me.ResourceName, script.Name, node.Number)
  3282. Return True
  3283. Case FirmwareVersionStatus.Current
  3284. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis,
  3285. "Instrument '{0}' script {1} on node {2} is up to date. Nothing to do.",
  3286. Me.ResourceName, script.Name, node.Number)
  3287. Return False
  3288. Case FirmwareVersionStatus.Missing
  3289. Me.OnMessageAvailable(TraceEventType.Information, synopsis,
  3290. "Instrument '{0}' custom firmware '{1}' version on node {2} is not known because script version function is not defined. Script will be deleted.",
  3291. Me.ResourceName, script.Name, node.Number)
  3292. Return True
  3293. Case FirmwareVersionStatus.Newer
  3294. If allowDeletingNewerScripts Then
  3295. Me.OnMessageAvailable(TraceEventType.Information, synopsis,
  3296. "Instrument '{0}' existing custom firmware '{1}' on node {2} version '{3}' is newer than the specified version '{4}'. The scripts will be deleted to allow uploading the older script.",
  3297. Me.ResourceName, script.Name, node.Number, script.EmbeddedFirmwareVersion, script.ReleasedFirmwareVersion)
  3298. Return True
  3299. Else
  3300. Me.OnMessageAvailable(TraceEventType.Information, synopsis,
  3301. "Instrument '{0}' existing custom firmware '{1}' on node {2} version '{3}' is newer than the specified version '{4}'. A newer version of the program is required. Script will not be deleted.",
  3302. Me.ResourceName, script.Name, node.Number, script.EmbeddedFirmwareVersion, script.ReleasedFirmwareVersion)
  3303. Return False
  3304. End If
  3305. Case FirmwareVersionStatus.Older
  3306. Me.OnMessageAvailable(TraceEventType.Information, synopsis,
  3307. "Instrument '{0}' existing custom firmware '{1}' on node {2} version '{3}' is older than the specified version '{4}'. Script will be deleted.",
  3308. Me.ResourceName, script.Name, node.Number, script.EmbeddedFirmwareVersion, script.ReleasedFirmwareVersion)
  3309. Return True
  3310. Case FirmwareVersionStatus.ReferenceUnknown
  3311. Me.OnMessageAvailable(TraceEventType.Warning, synopsis,
  3312. "Instrument '{0}' custom firmware '{1}' released version not given. Script will not be deleted.{2}{3}",
  3313. Me.ResourceName, script.Name,
  3314. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  3315. Return False
  3316. Case FirmwareVersionStatus.Unknown
  3317. Me.OnMessageAvailable(TraceEventType.Information, synopsis,
  3318. "Instrument '{0}' firmware '{1}' on node {2} version was not read. Script will be deleted.",
  3319. Me.ResourceName, script.Name, node.Number)
  3320. Return True
  3321. Case Else
  3322. Me.OnMessageAvailable(TraceEventType.Warning, synopsis,
  3323. "Instrument '{0}' encountered unhandled firmware version status {1} on node {2}. Nothing to do. Ignored.",
  3324. Me.ResourceName, validation, node.Number)
  3325. Return False
  3326. End Select
  3327. Return False
  3328. End Function
  3329. ''' <summary>
  3330. ''' Returns true if delete is required on any user script.
  3331. ''' </summary>
  3332. ''' <param name="scripts">Specifies the list of the scripts to be deleted.</param>
  3333. ''' <param name="node">Specifies the node.</param>
  3334. ''' <param name="refreshScriptsCatalog">Refresh catalog before checking if script exists.</param>
  3335. ''' <returns></returns>
  3336. ''' <remarks></remarks>
  3337. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  3338. Public Function IsDeleteUserScriptRequired(ByVal scripts As ScriptEntityCollection,
  3339. ByVal node As INodeEntity,
  3340. ByVal refreshScriptsCatalog As Boolean) As Boolean
  3341. If scripts Is Nothing Then
  3342. Throw New ArgumentNullException("scripts")
  3343. End If
  3344. If node Is Nothing Then
  3345. Throw New ArgumentNullException("node")
  3346. End If
  3347. ' true if any delete action was executed
  3348. ' Dim scriptsDeleted As Boolean = False
  3349. If scripts IsNot Nothing AndAlso scripts.Count > 0 Then
  3350. If refreshScriptsCatalog AndAlso Not Me.FetchSavedScripts(node) Then
  3351. Me.OnMessageAvailable(TraceEventType.Warning, "INSTRUMENT FAILED FETCHING CATALOG OF SAVED SCRIPTS",
  3352. "Instrument '{0}' failed fetching catalog of saved scripts from node {1}.{2}{3}",
  3353. Me.ResourceName, node.Number,
  3354. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  3355. Return False
  3356. End If
  3357. ' deletion of scripts must be done in reverse order.
  3358. For i As Integer = scripts.Count - 1 To 0 Step -1
  3359. Dim script As IScriptEntity = scripts.Item(i)
  3360. If script.IsModelMatch(node.ModelNumber) Then
  3361. Try
  3362. If Not script.IsBootScript AndAlso Me.IsDeleteUserScriptRequired(script, node, scripts.AllowDeletingNewerScripts) Then
  3363. ' stop in design time to make sure delete is not incorrect.
  3364. Debug.Assert(Not Debugger.IsAttached, "ARE YOU SURE?")
  3365. Return Me.IsDeleteUserScriptRequired(script, node, scripts.AllowDeletingNewerScripts)
  3366. End If
  3367. Catch ex As Exception
  3368. Me.OnMessageAvailable(TraceEventType.Error, "EXCEPTION OCCURRED TESTING IF DELETE IS REQUIRED",
  3369. "Exception occurred testing if delete is required for firmware {0} from node {1}. Details: {2}",
  3370. script.Name, node.Number, ex)
  3371. End Try
  3372. End If
  3373. Next
  3374. End If
  3375. Return False
  3376. End Function
  3377. ''' <summary>
  3378. ''' Returns true if delete is required on any node.
  3379. ''' </summary>
  3380. ''' <param name="scripts">Specifies the list of the scripts to be deleted.</param>
  3381. ''' <param name="nodes">Specifies the list of nodes on which scripts are deleted.</param>
  3382. ''' <param name="refreshScriptsCatalog">Refresh catalog before checking if script exists.</param>
  3383. ''' <returns></returns>
  3384. ''' <remarks></remarks>
  3385. Public Function IsDeleteUserScriptRequired(ByVal scripts As ScriptEntityCollection,
  3386. ByVal nodes As isr.Tsp.NodeEntityCollection,
  3387. ByVal refreshScriptsCatalog As Boolean) As Boolean
  3388. If scripts Is Nothing Then
  3389. Throw New ArgumentNullException("scripts")
  3390. End If
  3391. If nodes Is Nothing Then
  3392. Throw New ArgumentNullException("nodes")
  3393. End If
  3394. ' clear buffers before deleting.
  3395. Me._discardUnreadData(True)
  3396. For Each node As isr.Tsp.INodeEntity In nodes
  3397. If Me.IsDeleteUserScriptRequired(scripts, node, refreshScriptsCatalog) Then
  3398. Return True
  3399. End If
  3400. Next
  3401. Return False
  3402. End Function
  3403. ''' <summary>
  3404. ''' Deletes the user script.
  3405. ''' </summary>
  3406. ''' <param name="script">Specifies the <see cref="IScriptEntity">script</see>to delete</param>
  3407. ''' <param name="node">Specifies the system node</param>
  3408. ''' <param name="refreshScriptsCatalog">Refresh catalog before checking if script exists.</param>
  3409. ''' <returns>
  3410. ''' Returns true if script was deleted or did not exit.
  3411. ''' Returns false if deletion failed.
  3412. ''' </returns>
  3413. ''' <remarks></remarks>
  3414. Public Function DeleteUserScript(ByVal script As IScriptEntity,
  3415. ByVal node As INodeEntity,
  3416. ByVal refreshScriptsCatalog As Boolean) As Boolean
  3417. If script Is Nothing Then
  3418. Throw New ArgumentNullException("script")
  3419. End If
  3420. If node Is Nothing Then
  3421. Throw New ArgumentNullException("node")
  3422. End If
  3423. Dim synopsis As String = "Delete Custom Firmware"
  3424. If Me.IsNil(node, script.Name) Then
  3425. ' ignore error if nil
  3426. If ReportDeviceOperationOkay(node.Number, synopsis, "looking for script '{0}'. Ignoring error.", script.Name) Then
  3427. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis,
  3428. "Instrument '{0}' script {1} not found on node. Nothing to do.", Me.ResourceName, script.Name, node.Number)
  3429. End If
  3430. script.IsDeleted = True
  3431. Return True
  3432. End If
  3433. Me.DisplayLine(2, "Deleting {0}:{1}", node.Number, script.Name)
  3434. If node.IsController Then
  3435. If Me.DeleteScript(script.Name, refreshScriptsCatalog) Then
  3436. If ReportVisaDeviceOperationOkay(False, synopsis, "deleted {0}", script.Name) Then
  3437. Me.OnMessageAvailable(TraceEventType.Information, synopsis, "Instrument '{0}' deleted script {1} on node {2}.",
  3438. Me.ResourceName, script.Name, node.Number)
  3439. Else
  3440. Return False
  3441. End If
  3442. Else
  3443. If ReportVisaDeviceOperationOkay(False, synopsis, "deleting {0}", script.Name) Then
  3444. ' report failure if not an instrument or VISA error (handler returns Okay.)
  3445. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed deleting script {1} on node {2}.{3}{4}",
  3446. Me.ResourceName, script.Name, node.Number,
  3447. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  3448. End If
  3449. Return False
  3450. End If
  3451. ' do a garbage collection
  3452. Me.CollectGarbageWaitComplete(Me.DeleteTimeout, synopsis, "collecting garbage. Ignoring error.")
  3453. Else
  3454. If Me.DeleteScript(node.Number, script.Name, refreshScriptsCatalog) Then
  3455. If ReportDeviceOperationOkay(node.Number, synopsis, "deleted {0} on node {1}", script.Name, node.Number) Then
  3456. Me.OnMessageAvailable(TraceEventType.Information, synopsis, "Instrument '{0}' deleted {1} on node {2}.", Me.ResourceName, script.Name, node.Number)
  3457. Else
  3458. Return False
  3459. End If
  3460. Else
  3461. If ReportDeviceOperationOkay(node.Number, synopsis, "deleting {0} on node {1}", script.Name, node.Number) Then
  3462. ' report failure if not an instrument or VISA error (handler returns Okay.)
  3463. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed deleting {1} on node {2}.{3}{4}",
  3464. Me.ResourceName, script.Name, node.Number,
  3465. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  3466. End If
  3467. Return False
  3468. End If
  3469. ' do a garbage collection
  3470. Me.CollectGarbageWaitComplete(node.Number, Me.DeleteTimeout, synopsis, "collecting garbage on node {0}. Ignoring error.", node.Number)
  3471. End If
  3472. script.IsDeleted = True
  3473. Return True
  3474. End Function
  3475. ''' <summary>
  3476. ''' Deletes user scripts that are out-dated or where a deletion is set for the script.
  3477. ''' </summary>
  3478. ''' <param name="scripts">Specifies the list of the scripts to be deleted.</param>
  3479. ''' <param name="node">Specifies the node.</param>
  3480. ''' <param name="refreshScriptsCatalog">Refresh catalog before checking if script exists.</param>
  3481. ''' <param name="deleteOutDatedOnly">if set to <c>true</c> deletes only if scripts is out of date.</param>
  3482. ''' <returns><c>true</c> if success, <c>false</c> otherwise</returns>
  3483. ''' <exception cref="System.ArgumentNullException">scripts</exception>
  3484. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  3485. Public Function DeleteUserScripts(ByVal scripts As ScriptEntityCollection,
  3486. ByVal node As INodeEntity,
  3487. ByVal refreshScriptsCatalog As Boolean,
  3488. ByVal deleteOutdatedOnly As Boolean) As Boolean
  3489. If scripts Is Nothing Then
  3490. Throw New ArgumentNullException("scripts")
  3491. End If
  3492. If node Is Nothing Then
  3493. Throw New ArgumentNullException("node")
  3494. End If
  3495. Dim success As Boolean = True
  3496. Dim synopsis As String = "Deleting firmware"
  3497. ' true if any delete action was executed
  3498. Dim scriptsDeleted As Boolean = False
  3499. If scripts IsNot Nothing AndAlso scripts.Count > 0 Then
  3500. If refreshScriptsCatalog AndAlso Not Me.FetchSavedScripts(node) Then
  3501. Me.OnMessageAvailable(TraceEventType.Warning, synopsis,
  3502. "Instrument '{0}' failed fetching catalog of saved scripts from node {1}.{2}{3}",
  3503. Me.ResourceName, node.Number,
  3504. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  3505. Return False
  3506. End If
  3507. ' deletion of scripts must be done in reverse order.
  3508. For i As Integer = scripts.Count - 1 To 0 Step -1
  3509. Dim script As IScriptEntity = scripts.Item(i)
  3510. If script.IsModelMatch(node.ModelNumber) Then
  3511. Try
  3512. If Not script.IsDeleted AndAlso (script.RequiresDeletion OrElse
  3513. (Not deleteOutdatedOnly OrElse
  3514. Me.IsDeleteUserScriptRequired(script, node, scripts.AllowDeletingNewerScripts))) Then
  3515. If Me.DeleteUserScript(script, node, False) Then
  3516. ' mark that scripts were deleted, i.e., that any script was deleted
  3517. ' or if a script that existed no longer exists.
  3518. scriptsDeleted = True
  3519. Else
  3520. Me.OnMessageAvailable(TraceEventType.Information, synopsis, "Instrument '{0}' failed deleting script '{1}' from node {2}.",
  3521. Me.ResourceName, script.Name, node.Number)
  3522. success = False
  3523. End If
  3524. End If
  3525. Catch ex As Exception
  3526. Try
  3527. success = success AndAlso Me.IsNil(script.Name)
  3528. Me.OnMessageAvailable(TraceEventType.Error, synopsis, "Exception occurred deleting firmware {0} from node {1}. Details: {2}",
  3529. script.Name, node.Number, ex)
  3530. Catch
  3531. Me.OnMessageAvailable(TraceEventType.Error, synopsis, "Exception occurred checking existence after attempting deletion of firmware {0} from node {1}. Details: {2}",
  3532. script.Name, node.Number, ex)
  3533. success = False
  3534. End Try
  3535. End Try
  3536. End If
  3537. Next
  3538. End If
  3539. If scriptsDeleted Then
  3540. ' reset to refresh the instrument display.
  3541. Me.ResetNode(node)
  3542. End If
  3543. Return success
  3544. End Function
  3545. ''' <summary>
  3546. ''' Deletes user scripts from the remote instrument.
  3547. ''' </summary>
  3548. ''' <param name="scripts">Specifies the list of the scripts to be deleted.</param>
  3549. ''' <param name="nodes">Specifies the list of nodes on which scripts are deleted.</param>
  3550. ''' <param name="refreshScriptsCatalog">Refresh catalog before checking if script exists.</param>
  3551. ''' <param name="deleteOutDatedOnly">if set to <c>true</c> [delete out dated only].</param>
  3552. ''' <returns><c>true</c> if success, <c>false</c> otherwise</returns>
  3553. ''' <exception cref="System.ArgumentNullException">scripts</exception>
  3554. Public Function DeleteUserScripts(ByVal scripts As ScriptEntityCollection,
  3555. ByVal nodes As isr.Tsp.NodeEntityCollection,
  3556. ByVal refreshScriptsCatalog As Boolean,
  3557. ByVal deleteOutdatedOnly As Boolean) As Boolean
  3558. If scripts Is Nothing Then
  3559. Throw New ArgumentNullException("scripts")
  3560. End If
  3561. If nodes Is Nothing Then
  3562. Throw New ArgumentNullException("nodes")
  3563. End If
  3564. ' clear buffers before deleting.
  3565. Me._discardUnreadData(True)
  3566. Dim success As Boolean = True
  3567. For Each node As isr.Tsp.INodeEntity In nodes
  3568. success = success And Me.DeleteUserScripts(scripts, node, refreshScriptsCatalog, deleteOutdatedOnly)
  3569. Next
  3570. Return success
  3571. End Function
  3572. #End Region
  3573. #Region " TSPX: LOAD AND RUN SCRIPTS "
  3574. ''' <summary>
  3575. ''' Loads and executes the specified TSP script from file.
  3576. ''' </summary>
  3577. ''' <param name="script">Specifies reference to a valid <see cref="ScriptEntity">script</see></param>
  3578. ''' <param name="node">Specifies the node.</param>
  3579. ''' <returns>Returns True if ok.</returns>
  3580. ''' <remarks></remarks>
  3581. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  3582. Public Function LoadRunUserScript(ByVal script As IScriptEntity,
  3583. ByVal node As INodeEntity) As Boolean
  3584. If script Is Nothing Then
  3585. Throw New ArgumentNullException("script")
  3586. End If
  3587. If node Is Nothing Then
  3588. Throw New ArgumentNullException("node")
  3589. End If
  3590. Dim synopsis As String = "Load and run scripts"
  3591. Try
  3592. If Me.IsNil(node, script.Name) Then
  3593. If String.IsNullOrEmpty(script.Source) AndAlso script.Source.Length > 10 Then
  3594. Me.DisplayLine(2, "Attempted loading empty script {0}:{1}", node.Number, script.Name)
  3595. Return False
  3596. End If
  3597. If node.IsController Then
  3598. If Me.LoadUserScript(script) Then
  3599. If Not Me.RunUserScript(script) Then
  3600. Return False
  3601. End If
  3602. Else
  3603. Return False
  3604. End If
  3605. Else
  3606. If Me.LoadUserScript(node.Number, script) Then
  3607. If Not Me.RunUserScript(node.Number, script) Then
  3608. Return False
  3609. End If
  3610. Else
  3611. Return False
  3612. End If
  3613. End If
  3614. End If
  3615. Catch ex As Exception
  3616. Try
  3617. If Me.IsNil(node, script.Name) Then
  3618. Me.OnMessageAvailable(TraceEventType.Error, synopsis, "Exception occurred loading and running deleting firmware {0}. Details: {1}",
  3619. script.Name, ex)
  3620. Return False
  3621. Else
  3622. Me.OnMessageAvailable(TraceEventType.Error, synopsis, "Exception ignored loading and running deleting firmware {0}. Details: {1}",
  3623. script.Name, ex)
  3624. End If
  3625. Catch
  3626. Me.OnMessageAvailable(TraceEventType.Error, synopsis, "Exception occurred reading script status after attempting loading and running deleting firmware {0}. Details: {1}",
  3627. script.Name, ex)
  3628. Return False
  3629. End Try
  3630. End Try
  3631. Return True
  3632. End Function
  3633. ''' <summary>
  3634. ''' Loads and runs the user scripts on the controller instrument.
  3635. ''' </summary>
  3636. ''' <returns></returns>
  3637. ''' <remarks></remarks>
  3638. ''' <param name="scripts">Specifies the collection of scripts.</param>
  3639. ''' <param name="node">Specifies the node.</param>
  3640. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  3641. Public Function LoadRunUserScripts(ByVal scripts As ScriptEntityCollection,
  3642. ByVal node As INodeEntity) As Boolean
  3643. If scripts Is Nothing Then
  3644. Throw New ArgumentNullException("scripts")
  3645. End If
  3646. If node Is Nothing Then
  3647. Throw New ArgumentNullException("node")
  3648. End If
  3649. ' reset all status values so as to force a read.
  3650. ResetLocalKnownState()
  3651. ' true if any load and run action was executed
  3652. Dim resetRequired As Boolean = False
  3653. If scripts IsNot Nothing AndAlso scripts.Count > 0 Then
  3654. For Each script As IScriptEntity In scripts
  3655. If script.IsModelMatch(node.ModelNumber) Then
  3656. ' reset if a new script will be loaded.
  3657. resetRequired = resetRequired OrElse Me.IsNil(node, script.Name)
  3658. If Not LoadRunUserScript(script, node) Then
  3659. Return False
  3660. End If
  3661. End If
  3662. Next
  3663. End If
  3664. If resetRequired Then
  3665. ' reset to refresh the instrument display.
  3666. Me.ResetNode(node)
  3667. End If
  3668. Return True
  3669. End Function
  3670. ''' <summary>
  3671. ''' Loads and runs the user scripts on the controller instrument for the specified node.
  3672. ''' </summary>
  3673. ''' <returns></returns>
  3674. ''' <remarks></remarks>
  3675. ''' <param name="scripts">Specifies the collection of scripts.</param>
  3676. ''' <param name="nodes">Specifies the nodes.</param>
  3677. Public Function LoadRunUserScripts(ByVal scripts As ScriptEntityCollection,
  3678. ByVal nodes As isr.Tsp.NodeEntityCollection) As Boolean
  3679. If scripts Is Nothing Then
  3680. Throw New ArgumentNullException("scripts")
  3681. End If
  3682. If nodes Is Nothing Then
  3683. Throw New ArgumentNullException("nodes")
  3684. End If
  3685. ' clear buffers before deleting.
  3686. Me._discardUnreadData(True)
  3687. For Each node As INodeEntity In nodes
  3688. If Not LoadRunUserScripts(scripts, node) Then
  3689. Return False
  3690. End If
  3691. Next
  3692. Return True
  3693. End Function
  3694. ''' <summary>
  3695. ''' Copies a script source.
  3696. ''' </summary>
  3697. ''' <param name="sourceName">The name of the source script.</param>
  3698. ''' <param name="destinationName">The name of the destination script.</param>
  3699. ''' <returns></returns>
  3700. ''' <remarks>For binary scripts, the controller and remote nodes must be binary compatible.</remarks>
  3701. Public Function CopyScript(ByVal sourceName As String, ByVal destinationName As String) As Boolean
  3702. ' loads and runs the specified script.
  3703. Return Me.WriteLine("{1}=script.new( {0}.source , '{1}' ) waitcomplete()", sourceName, destinationName)
  3704. End Function
  3705. ''' <summary>
  3706. ''' Copies a script from the controller node to a remote node.
  3707. ''' </summary>
  3708. ''' <param name="nodeNumber"></param>
  3709. ''' <param name="sourceName">The script name on the controller node.</param>
  3710. ''' <param name="destinationName">The script name on the remote node.</param>
  3711. ''' <returns></returns>
  3712. ''' <remarks>For binary scripts, the controller and remote nodes must be binary compatible.</remarks>
  3713. Public Function CopyScript(ByVal nodeNumber As Integer, ByVal sourceName As String, ByVal destinationName As String) As Boolean
  3714. ' loads and runs the specified script.
  3715. Dim commands As String = String.Format(Globalization.CultureInfo.CurrentCulture,
  3716. "node[{0}].execute('waitcomplete() {2}=script.new({1}.source,[[{2}]])') waitcomplete({0}) waitcomplete()",
  3717. nodeNumber, sourceName, destinationName)
  3718. Return LoadString(commands)
  3719. End Function
  3720. ''' <summary>
  3721. ''' Copies script source from one script to another.
  3722. ''' </summary>
  3723. ''' <param name="node">Specifies a node on which to copy.</param>
  3724. ''' <param name="sourceName">The script name on the controller node.</param>
  3725. ''' <param name="destinationName">The script name on the remote node.</param>
  3726. ''' <returns></returns>
  3727. ''' <remarks>For binary scripts, the controller and remote nodes must be binary compatible.</remarks>
  3728. Public Function CopyScript(ByVal node As INodeEntity, ByVal sourceName As String, ByVal destinationName As String) As Boolean
  3729. If node Is Nothing Then
  3730. Throw New ArgumentNullException("node")
  3731. End If
  3732. If node.IsController Then
  3733. Return Me.CopyScript(sourceName, destinationName)
  3734. Else
  3735. Return Me.CopyScript(node.Number, sourceName, destinationName)
  3736. End If
  3737. End Function
  3738. ''' <summary>
  3739. ''' Loads and runs an anonymous script.
  3740. ''' </summary>
  3741. ''' <param name="commands">Specifies the script commands.</param>
  3742. ''' <returns></returns>
  3743. ''' <remarks></remarks>
  3744. Public Function LoadRunAnonymousScript(ByVal commands As String) As Boolean
  3745. Dim prefix As String = "loadandrunscript"
  3746. Dim suffix As String = "endscript waitcomplete()"
  3747. Dim loadCommand As String = String.Format(Globalization.CultureInfo.CurrentCulture, "{1}{0}{2}{0}{3}",
  3748. Environment.NewLine, prefix, commands, suffix)
  3749. Return LoadString(loadCommand)
  3750. End Function
  3751. ''' <summary>
  3752. ''' Builds a script for loading a script to the remote node.
  3753. ''' </summary>
  3754. ''' <param name="nodeNumber">Specifies the remote node number</param>
  3755. ''' <param name="script">Specifies the script.</param>
  3756. ''' <param name="loadingScriptName">Specifies the name of the loading script that will be deleted after the
  3757. ''' process is done.</param>
  3758. ''' <returns></returns>
  3759. ''' <remarks></remarks>
  3760. Private Shared Function buildScriptLoaderScript(ByVal nodeNumber As Integer,
  3761. ByVal script As IScriptEntity, ByVal loadingScriptName As String) As System.Text.StringBuilder
  3762. If script Is Nothing Then
  3763. Throw New ArgumentNullException("script")
  3764. End If
  3765. Dim prefix As String = "loadstring(table.concat("
  3766. Dim suffix As String = "))()"
  3767. Dim binaryDecorationRequire As Boolean = script.IsBinary AndAlso Not script.Source.Contains(prefix)
  3768. Dim loadCommands As New System.Text.StringBuilder(script.Source.Length + 512)
  3769. loadCommands.AppendFormat("loadandrunscript {0}", loadingScriptName)
  3770. loadCommands.AppendLine()
  3771. loadCommands.AppendLine("do")
  3772. loadCommands.AppendFormat(Globalization.CultureInfo.CurrentCulture,
  3773. "node[{0}].dataqueue.add([[", nodeNumber)
  3774. If binaryDecorationRequire Then
  3775. loadCommands.Append(prefix)
  3776. End If
  3777. loadCommands.AppendLine(script.Source)
  3778. If binaryDecorationRequire Then
  3779. loadCommands.AppendLine(suffix)
  3780. End If
  3781. loadCommands.AppendFormat(Globalization.CultureInfo.CurrentCulture, "]]) waitcomplete()", nodeNumber)
  3782. loadCommands.AppendLine()
  3783. loadCommands.AppendFormat(Globalization.CultureInfo.CurrentCulture,
  3784. "node[{0}].execute([[waitcomplete() {1}=script.new(dataqueue.next(),'{1}')]])",
  3785. nodeNumber, script.Name)
  3786. loadCommands.AppendLine()
  3787. loadCommands.AppendFormat(Globalization.CultureInfo.CurrentCulture,
  3788. "waitcomplete({0})", nodeNumber)
  3789. loadCommands.AppendLine(" waitcomplete()")
  3790. loadCommands.AppendLine("end")
  3791. loadCommands.AppendLine("endscript")
  3792. Return loadCommands
  3793. End Function
  3794. ''' <summary>
  3795. ''' Create a new script on the remote node.
  3796. ''' </summary>
  3797. ''' <param name="nodeNumber">Specifies the node number</param>
  3798. ''' <param name="script"></param>
  3799. ''' <returns></returns>
  3800. ''' <remarks></remarks>
  3801. Public Function UploadScript(ByVal nodeNumber As Integer, ByVal script As IScriptEntity) As Boolean
  3802. If script Is Nothing Then
  3803. Throw New ArgumentNullException("script")
  3804. End If
  3805. Dim synopsis As String = "Create Node Script"
  3806. If script.IsBinary OrElse (Not Me.IsNil(script.Name) AndAlso IsBinaryScript(script.Name, Me._controllerNode)) Then
  3807. ' clear the data queue.
  3808. Me.ClearDataQueue(nodeNumber, False)
  3809. Dim tempName As String = "isr_temp"
  3810. Dim scriptLoaderScript As String = buildScriptLoaderScript(nodeNumber, script, tempName).ToString
  3811. ' load and ran the temporary script.
  3812. If LoadString(scriptLoaderScript) Then
  3813. ' enable wait completion (the wait complete command is included in the loader script
  3814. If Me.EnableWaitComplete Then
  3815. If Me.AwaitOperationCompleted(script.Timeout, script.Timeout \ 10 + 10) Then
  3816. If Not Me.ReportDeviceOperationOkay(nodeNumber, synopsis, "loading script '{0}'", tempName) Then
  3817. Return False
  3818. End If
  3819. Else
  3820. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' timed out waiting loading script '{1}'.{2}{3}",
  3821. Me.ResourceName, tempName,
  3822. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  3823. Return False
  3824. End If
  3825. Else
  3826. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed enabling wait completion after loading script '{1}'.{2}{3}",
  3827. Me.ResourceName, tempName,
  3828. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  3829. Return False
  3830. End If
  3831. ElseIf Not Me.ReportDeviceOperationOkay(nodeNumber, synopsis, "loading and running script '{0}'", tempName) Then
  3832. Return False
  3833. End If
  3834. ' remove the temporary script if there.
  3835. If Not IsNil(tempName) Then
  3836. Me.DeleteScript(tempName, False)
  3837. End If
  3838. Else
  3839. ' if scripts is already stored in the controller node in non-binary format, just
  3840. ' copy it (upload) from the controller to the remote node.
  3841. If Not Me.UploadScript(nodeNumber, script.Name, script.Timeout) Then
  3842. Return False
  3843. End If
  3844. End If
  3845. ' verify that the script was loaded.
  3846. ' check if the script short name exists.
  3847. If Me.WaitNotNil(nodeNumber, script.Name, script.Timeout) Then
  3848. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis, "Instrument '{0}' loaded script '{1}' to node {2}.",
  3849. Me.ResourceName, script.Name, nodeNumber)
  3850. Return True
  3851. Else
  3852. ' if script short name not found, check to see if the script long name is found.
  3853. Dim fullName As String = "script.user.scripts." & script.Name
  3854. If Me.WaitNotNil(nodeNumber, fullName, script.Timeout) Then
  3855. ' in design mode, assert this as a problem.
  3856. ' 3783. this was asserted the first time after upgrading the 3706 to firmware 1.32.a
  3857. Debug.Assert(Not Debugger.IsAttached, "Failed setting script short name")
  3858. ' assign the new script name
  3859. If Me.ExecuteCommandWaitComplete(nodeNumber, Me._saveTimeout, False, "{0} = {1} waitcomplete() ", script.Name, fullName) Then
  3860. If Me.WaitNotNil(nodeNumber, script.Name, script.Timeout) Then
  3861. Return True
  3862. Else
  3863. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed referencing script '{1}' using '{2}' on node {3}--new script not found on the remote node.{4}{5}",
  3864. Me.ResourceName, script.Name, fullName, nodeNumber,
  3865. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  3866. Return False
  3867. End If
  3868. Else
  3869. If Me.ReportVisaDeviceOperationOkay(False, synopsis, "uploading script '{0}'.", script.Name) Then
  3870. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed referencing script '{1}' using name '{2}' on node {3}--new script not found on the remote node.{4}{5}",
  3871. Me.ResourceName, fullName, script.Name, nodeNumber,
  3872. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  3873. End If
  3874. Return False
  3875. End If
  3876. Else
  3877. ' if both long and short names not found, report failure.
  3878. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed uploading script '{1}' to node {2} from script '{3}'--new script not found on the remote node.{4}{5}",
  3879. Me.ResourceName, fullName, nodeNumber, script.Name,
  3880. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  3881. Return False
  3882. End If
  3883. End If
  3884. End Function
  3885. ''' <summary>
  3886. ''' Uploads a script from the controller node to a remote node using the same name on the remote node.
  3887. ''' Does not require having the ISR Support script on the controller node.
  3888. ''' </summary>
  3889. ''' <param name="nodeNumber"></param>
  3890. ''' <param name="scriptName">The script name on the controller node.</param>
  3891. ''' <returns></returns>
  3892. ''' <remarks>For binary scripts, the controller and remote nodes must be binary compatible.</remarks>
  3893. Public Function UploadScript(ByVal nodeNumber As Integer, ByVal scriptName As String,
  3894. ByVal timeout As Integer) As Boolean
  3895. If scriptName Is Nothing Then
  3896. Throw New ArgumentNullException("scriptName")
  3897. End If
  3898. Dim synopsis As String = "Upload Node Script"
  3899. ' NOTE: WAIT COMPLETE is required on the system before a wait complete is tested on the node
  3900. ' otherwise getting error 1251.
  3901. Dim commands As New System.Text.StringBuilder(1024)
  3902. If Me.IsNil(Scripts.SupportScript(Me.ControllerNode).Namespaces) Then
  3903. ' loads and runs the specified script.
  3904. commands.AppendFormat(Globalization.CultureInfo.CurrentCulture,
  3905. "node[{0}].dataqueue.add({1}.source) waitcomplete()", nodeNumber, scriptName)
  3906. commands.AppendLine()
  3907. commands.AppendFormat(Globalization.CultureInfo.CurrentCulture,
  3908. "node[{0}].execute('waitcomplete() {1}=script.new(dataqueue.next(),[[{1}]])')",
  3909. nodeNumber, scriptName)
  3910. Else
  3911. commands.AppendFormat(Globalization.CultureInfo.CurrentCulture,
  3912. "isr.script.uploadScript(node[{0}],{1})", nodeNumber, scriptName)
  3913. End If
  3914. commands.AppendLine()
  3915. commands.AppendLine("waitcomplete(0)")
  3916. If Not LoadString(commands.ToString) Then
  3917. Return False
  3918. End If
  3919. Me.IssueWaitComplete(0)
  3920. If Me.AwaitOperationCompleted(timeout, timeout \ 10 + 10) Then
  3921. If Not Me.ReportDeviceOperationOkay(nodeNumber, synopsis, "timeout uploading script '{0}' to node {1}", scriptName, nodeNumber) Then
  3922. Return False
  3923. End If
  3924. Else
  3925. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' timed out waiting loading script '{1}' on node {2}.{3}{4}",
  3926. Me.ResourceName, scriptName, nodeNumber,
  3927. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  3928. Return False
  3929. End If
  3930. Return True
  3931. End Function
  3932. ''' <summary>
  3933. ''' Loads the specified script from the local to the remote node.
  3934. ''' </summary>
  3935. ''' <param name="nodeNumber">Specifies the node number</param>
  3936. ''' <param name="script">Specifies reference to a valid <see cref="ScriptEntity">script</see></param>
  3937. ''' <returns></returns>
  3938. ''' <remarks>Will not load a script list that includes the create script command.</remarks>
  3939. Public Function LoadUserScript(ByVal nodeNumber As Integer, ByVal script As IScriptEntity) As Boolean
  3940. If script Is Nothing Then
  3941. Throw New ArgumentNullException("script")
  3942. End If
  3943. Dim synopsis As String = "Load Node Script"
  3944. If Not Me.IsNil(nodeNumber, script.Name) Then
  3945. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis, "Instrument '{0}' script {1} already exists on node {2}. Nothing to do.",
  3946. Me.ResourceName, script.Name, nodeNumber)
  3947. Return True
  3948. End If
  3949. Me.DisplayLine(2, "Uploading {0}:{1}", nodeNumber, script.Name)
  3950. If Not Me.UploadScript(nodeNumber, script) Then
  3951. Me.DisplayLine(2, "Failed uploading {0}:{1}", nodeNumber, script.Name)
  3952. Return False
  3953. End If
  3954. Me.DisplayLine(2, "Verifying {0}:{1}", nodeNumber, script.Name)
  3955. If Not Me.WaitNotNil(nodeNumber, script.Name, Me._saveTimeout) Then
  3956. Me.DisplayLine(2, "{0}:{1} not found after loading", nodeNumber, script.Name)
  3957. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed loading script '{1}' to node {2}--new script not found on the remote node.{3}{4}",
  3958. Me.ResourceName, script.Name, nodeNumber,
  3959. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  3960. Return False
  3961. End If
  3962. ' do a garbage collection
  3963. Me.DisplayLine(2, "Cleaning local node")
  3964. Me.CollectGarbageWaitComplete(script.Timeout, synopsis, "collecting garbage after loading script {0} on node {1}. Error ignored.", script.Name, nodeNumber)
  3965. ' do a garbage collection
  3966. Me.DisplayLine(2, "Cleaning node {0}", nodeNumber)
  3967. Me.CollectGarbageWaitComplete(nodeNumber, script.Timeout, synopsis, "collecting garbage after loading script {0} on node {1}. Error ignored.", script.Name, nodeNumber)
  3968. Me.DisplayLine(2, "{0}:{1} Loaded", nodeNumber, script.Name)
  3969. Me.OnMessageAvailable(TraceEventType.Information, synopsis, "Instrument '{0}' {1} script loaded from local node to node {2}.",
  3970. Me.ResourceName, script.Name, nodeNumber)
  3971. Return True
  3972. End Function
  3973. ''' <summary>
  3974. ''' Loads the specified TSP script from code.
  3975. ''' </summary>
  3976. ''' <param name="script">Specifies reference to a valid <see cref="ScriptEntity">script</see></param>
  3977. ''' <returns>Returns True if ok.</returns>
  3978. ''' <remarks></remarks>
  3979. Public Function LoadUserScript(ByVal script As IScriptEntity) As Boolean
  3980. If script Is Nothing Then
  3981. Throw New ArgumentNullException("script")
  3982. End If
  3983. Dim synopsis As String = "Load Custom Firmware"
  3984. If Not Me.IsNil(script.Name) Then
  3985. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis, "Instrument '{0}' script {1} already exists.", Me.ResourceName, script.Name)
  3986. Return True
  3987. End If
  3988. Me.DisplayLine(2, "Loading {0}", script.Name)
  3989. If Not Me.LoadScript(script.Name, script.Source) Then
  3990. If Me.ReportVisaDeviceOperationOkay(False, synopsis, "loading {0}", script.Name) Then
  3991. ' report failure if not an instrument or VISA error (handler returns Okay.)
  3992. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed loading {1}.{2}{3}",
  3993. Me.ResourceName, script.Name,
  3994. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  3995. End If
  3996. Return False
  3997. End If
  3998. ' do a garbage collection
  3999. Me.CollectGarbageWaitComplete(script.Timeout, synopsis, "collecting garbage. Error ignored")
  4000. Me.OnMessageAvailable(TraceEventType.Information, synopsis, "Instrument '{0}' {1} script loaded.", Me.ResourceName, script.Name)
  4001. Me.DisplayLine(2, "{0} Loaded", script.Name)
  4002. Return True
  4003. End Function
  4004. ''' <summary>
  4005. ''' Executes the specified TSP script from file.
  4006. ''' </summary>
  4007. ''' <param name="script">Specifies reference to a valid <see cref="ScriptEntity">script</see></param>
  4008. ''' <returns>Returns True if ok.</returns>
  4009. ''' <remarks></remarks>
  4010. ''' <history date="05/13/2009" by="David Hary" revision="3.0.3420.x">
  4011. ''' Modified to run irrespective of the existence of the name spaces because
  4012. ''' a new script can be loaded on top of existing old code and the new version number
  4013. ''' will not materialize..
  4014. ''' </history>
  4015. Public Function RunUserScript(ByVal script As IScriptEntity) As Boolean
  4016. Dim synopsis As String = "Run Custom Firmware"
  4017. If script Is Nothing Then
  4018. Throw New ArgumentNullException("script")
  4019. End If
  4020. If Me.IsNil(script.Name) Then
  4021. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed running {1} because it does not exist.{2}{3}",
  4022. Me.ResourceName, script.Name,
  4023. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4024. Return False
  4025. End If
  4026. #If False Then
  4027. ' taken out to run always.
  4028. If False AndAlso script.Namespaces IsNot Nothing AndAlso script.Namespaces.Length > 0 AndAlso Not Me.IsNil(script.Namespaces) Then
  4029. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis, "Instrument '{0}' script {1} already run. Nothing to do.",
  4030. Me.ResourceName, script.Name)
  4031. Return True
  4032. End If
  4033. #End If
  4034. Me.DisplayLine(2, "Running {0}", script.Name)
  4035. If Not Me.RunScript(script.Name, script.Timeout) Then
  4036. Me.DisplayLine(2, "Failed running {0}", script.Name)
  4037. If Me.ReportVisaDeviceOperationOkay(False, synopsis, "running {0}", script.Name) Then
  4038. ' report failure if not an instrument or VISA error (handler returns Okay.)
  4039. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed running {1}.{2}{3}",
  4040. Me.ResourceName, script.Name,
  4041. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4042. End If
  4043. Return False
  4044. End If
  4045. If Me.IsNil(script.Name) Then
  4046. If Me.ReportVisaDeviceOperationOkay(False, synopsis, "script {0} not found after running from {1}", script.Name) Then
  4047. ' report failure if not an instrument or VISA error (handler returns Okay.)
  4048. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed running script {1}.{2}{3}",
  4049. Me.ResourceName, script.Name,
  4050. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4051. End If
  4052. Return False
  4053. ElseIf script.Namespaces IsNot Nothing AndAlso script.Namespaces.Length > 0 AndAlso Me.IsNil(script.Namespaces) Then
  4054. If Me.ReportVisaDeviceOperationOkay(False, synopsis, "some of the namespace(s) {0} are nil after running {1}", script.NamespaceList, script.Name) Then
  4055. ' if not a visa error, report the specific namespaces.
  4056. For Each value As String In script.Namespaces
  4057. If Me.IsNil(value) Then
  4058. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' namespace {1} is nil.{2}{3}",
  4059. Me.ResourceName, value,
  4060. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4061. End If
  4062. Next
  4063. End If
  4064. Return False
  4065. Else
  4066. Me.DisplayLine(2, "Done running {0}", script.Name)
  4067. Me.OnMessageAvailable(TraceEventType.Information, synopsis, "Instrument '{0}' {1} script run okay.", Me.ResourceName, script.Name)
  4068. Return True
  4069. End If
  4070. Return True
  4071. End Function
  4072. ''' <summary>
  4073. ''' Executed a loaded script on the local node.
  4074. ''' </summary>
  4075. ''' <param name="nodeNumber">Specifies the node number</param>
  4076. ''' <param name="script">Specifies reference to a valid <see cref="ScriptEntity">script</see></param>
  4077. ''' <returns></returns>
  4078. ''' <remarks>
  4079. ''' </remarks>
  4080. ''' <history date="05/13/2009" by="David Hary" revision="3.0.3420.x">
  4081. ''' Modified to run irrespective of the existence of the name spaces because
  4082. ''' a new script can be loaded on top of existing old code and the new version number
  4083. ''' will not materialize..
  4084. ''' </history>
  4085. Public Function RunUserScript(ByVal nodeNumber As Integer, ByVal script As IScriptEntity) As Boolean
  4086. If script Is Nothing Then
  4087. Throw New ArgumentNullException("script")
  4088. End If
  4089. Dim synopsis As String = "Run Node Firmware"
  4090. If Me.IsNil(nodeNumber, script.Name) Then
  4091. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed running {1} because it does not exist on node {2}.{3}{4}",
  4092. Me.ResourceName, script.Name, nodeNumber,
  4093. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4094. Return False
  4095. End If
  4096. #If False Then
  4097. If False AndAlso script.Namespaces IsNot Nothing AndAlso script.Namespaces.Length > 0 AndAlso Not Me.IsNil(nodeNumber, script.Namespaces) Then
  4098. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis, "Instrument '{0}' script {1} already run on node {2}. Nothing to do.",
  4099. Me.ResourceName, script.Name, nodeNumber)
  4100. Return True
  4101. End If
  4102. #End If
  4103. Me.DisplayLine(2, "Running {0}:{1}", nodeNumber, script.Name)
  4104. If Me.ExecuteCommandWaitComplete(nodeNumber, script.Timeout, False, "script.user.scripts.{0}()", script.Name) Then
  4105. If Not Me.ReportDeviceOperationOkay(nodeNumber, synopsis, "running '{0}' script on node {1}", script.Name, nodeNumber) Then
  4106. Me.DisplayLine(2, "Failed running {0}:{1}", nodeNumber, script.Name)
  4107. End If
  4108. Else
  4109. Me.DisplayLine(2, "Failed running {0}:{1}", nodeNumber, script.Name)
  4110. If Not Me.ReportDeviceOperationOkay(nodeNumber, synopsis, "running '{0}' script on node {1}", script.Name, nodeNumber) Then
  4111. Else
  4112. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed running script {1} on node {2}.{3}{4}",
  4113. Me.ResourceName, script.Name, nodeNumber,
  4114. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4115. End If
  4116. End If
  4117. ' do a garbage collection
  4118. Me.DisplayLine(2, "Waiting cleanup node {0}", nodeNumber)
  4119. Me.CollectGarbageWaitComplete(nodeNumber, script.Timeout, synopsis, "collecting garbage after running script {0} on node {1}. Error ignored.", script.Name, nodeNumber)
  4120. If Me.IsNil(nodeNumber, script.Name) Then
  4121. If Me.ReportDeviceOperationOkay(nodeNumber, synopsis, "script {0} not found after running on node {1}", script.Name, nodeNumber) Then
  4122. ' report failure if not an instrument or VISA error (handler returns Okay.)
  4123. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed loading script {1} to node {2}.{3}{4}",
  4124. Me.ResourceName, script.Name, nodeNumber,
  4125. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4126. End If
  4127. Return False
  4128. ElseIf script.Namespaces IsNot Nothing AndAlso script.Namespaces.Length > 0 AndAlso Me.IsNil(nodeNumber, script.Namespaces) Then
  4129. If Me.ReportDeviceOperationOkay(nodeNumber, synopsis, "some of the namespace(s) {0} are nil after running {1} on node {2}",
  4130. script.NamespaceList, script.Name, nodeNumber) Then
  4131. ' if not a visa error, report the specific namespaces.
  4132. For Each value As String In script.Namespaces
  4133. If Me.IsNil(value) Then
  4134. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' namespace {1} is nil on node {2}.{3}{4}",
  4135. Me.ResourceName, value, nodeNumber,
  4136. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4137. End If
  4138. Next
  4139. End If
  4140. Return False
  4141. Else
  4142. Me.DisplayLine(2, "Done running {0}:{1}", nodeNumber, script.Name)
  4143. Me.OnMessageAvailable(TraceEventType.Information, synopsis, "Instrument '{0}' {1} script run on node {2}.", Me.ResourceName, script.Name, nodeNumber)
  4144. Return True
  4145. End If
  4146. Return True
  4147. End Function
  4148. #End Region
  4149. #Region " TSPX: AUTO RUN SCRIPTS "
  4150. ''' <summary>
  4151. ''' Builds the commands for the auto run script.
  4152. ''' </summary>
  4153. ''' <param name="commands">Specifies the list of commands to add to the script.</param>
  4154. ''' <param name="scripts">Specifies the list of scripts which to include in the run.</param>
  4155. ''' <returns></returns>
  4156. ''' <remarks></remarks>
  4157. Public Shared Function BuildAutoRunScript(ByVal commands As System.Text.StringBuilder,
  4158. ByVal scripts As ScriptEntityCollection) As String
  4159. If scripts Is Nothing Then
  4160. Throw New ArgumentNullException("scripts")
  4161. End If
  4162. Dim script As New System.Text.StringBuilder(1024)
  4163. Dim uniqueScripts As New Collections.Specialized.ListDictionary()
  4164. ' add code to run all scripts other than the boot script
  4165. If scripts IsNot Nothing Then
  4166. For Each scriptEntity As IScriptEntity In scripts
  4167. If Not String.IsNullOrEmpty(scriptEntity.Name) Then
  4168. If Not scriptEntity.IsBootScript Then
  4169. If Not uniqueScripts.Contains(scriptEntity.Name) Then
  4170. uniqueScripts.Add(scriptEntity.Name, scriptEntity)
  4171. script.AppendFormat("{0}.run()", scriptEntity.Name)
  4172. script.AppendLine()
  4173. End If
  4174. End If
  4175. End If
  4176. Next
  4177. End If
  4178. ' add the custom commands.
  4179. If commands IsNot Nothing AndAlso commands.Length > 1 Then
  4180. script.AppendLine(commands.ToString)
  4181. End If
  4182. Return script.ToString
  4183. End Function
  4184. #End Region
  4185. #Region " TSPX: SAVE SCRIPTS "
  4186. ''' <summary>
  4187. ''' Returns true if save is required fr the specified script.
  4188. ''' Presumes list of saved scripts was retrieved.
  4189. ''' </summary>
  4190. ''' <param name="scriptName">Specifies the script to save.</param>
  4191. ''' <param name="node">Specifies the node.</param>
  4192. ''' <param name="isSaveAsBinary">Specifies the condition requesting saving the source as binary</param>
  4193. ''' <param name="isBootScript">Specifies the condition indicating if this is a boot script</param>
  4194. ''' <returns></returns>
  4195. ''' <remarks></remarks>
  4196. Public Function IsSaveRequired(ByVal scriptName As String, ByVal node As INodeEntity,
  4197. ByVal isSaveAsBinary As Boolean, ByVal isBootScript As Boolean) As Boolean
  4198. If scriptName Is Nothing Then
  4199. Throw New ArgumentNullException("scriptName")
  4200. End If
  4201. If node Is Nothing Then
  4202. Throw New ArgumentNullException("node")
  4203. End If
  4204. Return (isSaveAsBinary AndAlso Not Me.IsBinaryScript(scriptName, node)) OrElse
  4205. Not Me.SavedScriptExists(scriptName, node, False) OrElse
  4206. (isBootScript AndAlso node.BootScriptSaveRequired)
  4207. End Function
  4208. ''' <summary>
  4209. ''' Saves the user script in non-volatile memory.
  4210. ''' </summary>
  4211. ''' <param name="scriptName">Specifies the script to save.</param>
  4212. ''' <param name="node">Specifies the node.</param>
  4213. ''' <param name="isSaveAsBinary">Specifies the condition requesting saving the source as binary</param>
  4214. ''' <param name="isBootScript">Specifies the condition indicating if this is a boot script</param>
  4215. ''' <returns></returns>
  4216. ''' <remarks></remarks>
  4217. Public Function SaveUserScript(ByVal scriptName As String,
  4218. ByVal node As INodeEntity,
  4219. ByVal isSaveAsBinary As Boolean, ByVal isBootScript As Boolean,
  4220. ByVal timeout As Integer) As Boolean
  4221. If scriptName Is Nothing Then
  4222. Throw New ArgumentNullException("scriptName")
  4223. End If
  4224. If node Is Nothing Then
  4225. Throw New ArgumentNullException("node")
  4226. End If
  4227. Dim synopsis As String = "Save Custom Firmware"
  4228. If Me.IsNil(node, scriptName) Then
  4229. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' custom firmware {1} not saved on node {2} because it is not loaded. Error may be ignored.{3}{4}",
  4230. Me.ResourceName, scriptName, node.Number,
  4231. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4232. Return False
  4233. End If
  4234. If IsSaveRequired(scriptName, node, isSaveAsBinary, isBootScript) Then
  4235. If Not isBootScript Then
  4236. ' if a script is saved, boot save is required.
  4237. node.BootScriptSaveRequired = True
  4238. End If
  4239. ' do a garbage collection
  4240. Me.DisplayLine(2, "Cleaning node {0}", node.Number)
  4241. Me.CollectGarbageWaitComplete(node, timeout, synopsis, "collecting garbage before saving script {0} on node {1}. Error ignored.",
  4242. scriptName, node.Number)
  4243. Me.DisplayLine(2, "Saving {0}:{1}", node.Number, scriptName)
  4244. If Me.SaveScript(scriptName, node, isSaveAsBinary, isBootScript) Then
  4245. ' if saved boot script, boot script save no longer required.
  4246. If isBootScript Then
  4247. node.BootScriptSaveRequired = False
  4248. End If
  4249. Me.OnMessageAvailable(TraceEventType.Information, synopsis, "Instrument '{0}' saved script {1} on node {2}.",
  4250. Me.ResourceName, scriptName, node.Number)
  4251. Else
  4252. If Me.ReportDeviceOperationOkay(node.Number, synopsis, "saving script {0} on node {1}", scriptName, node.Number) Then
  4253. ' report failure if not an instrument or VISA error (handler returns Okay.)
  4254. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed saving script {1} on node {2}.{3}{4}",
  4255. Me.ResourceName, scriptName, node.Number,
  4256. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4257. End If
  4258. Return False
  4259. End If
  4260. Else
  4261. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis, "Instrument '{0}' script {1} already saved on node {2}",
  4262. Me.ResourceName, scriptName, node.Number)
  4263. End If
  4264. Return True
  4265. End Function
  4266. ''' <summary>
  4267. ''' Saves the user scripts.
  4268. ''' </summary>
  4269. ''' <param name="scripts">Specifies the list of scripts to save.</param>
  4270. ''' <param name="node">Specifies the node.</param>
  4271. ''' <returns></returns>
  4272. ''' <remarks></remarks>
  4273. Public Function SaveUserScripts(ByVal scripts As ScriptEntityCollection,
  4274. ByVal node As INodeEntity) As Boolean
  4275. If scripts Is Nothing Then
  4276. Throw New ArgumentNullException("scripts")
  4277. End If
  4278. If node Is Nothing Then
  4279. Throw New ArgumentNullException("node")
  4280. End If
  4281. Dim synopsis As String = "Save Firmware"
  4282. Dim success As Boolean = True
  4283. ' true if any save action was executed
  4284. Dim resetRequired As Boolean = False
  4285. If Not Me.FetchSavedScripts(node) Then
  4286. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "Instrument '{0}' failed fetching catalog of saved scripts from node {1}.{2}{3}",
  4287. Me.ResourceName, node.Number,
  4288. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4289. Return False
  4290. End If
  4291. If scripts IsNot Nothing Then
  4292. For Each script As IScriptEntity In scripts
  4293. If script.IsModelMatch(node.ModelNumber) AndAlso Not String.IsNullOrEmpty(script.Name) Then
  4294. If Not IsNil(node, script.Name) Then
  4295. resetRequired = resetRequired OrElse IsSaveRequired(script.Name, node,
  4296. ((script.FileFormat And ScriptFileFormats.Binary) <> 0),
  4297. script.IsBootScript)
  4298. success = success And Me.SaveUserScript(script.Name, node,
  4299. ((script.FileFormat And ScriptFileFormats.Binary) <> 0),
  4300. script.IsBootScript, script.Timeout)
  4301. End If
  4302. End If
  4303. Next
  4304. End If
  4305. If resetRequired Then
  4306. ' reset to refresh the instrument display.
  4307. Me.ResetNode(node)
  4308. End If
  4309. If success Then
  4310. Me.DisplayLine(2, "All scripts saved on node {0}", node.Number)
  4311. Else
  4312. Me.DisplayLine(2, "Failed saving script on node {0}", node.Number)
  4313. End If
  4314. Return success
  4315. End Function
  4316. ''' <summary>
  4317. ''' Saves all users scripts.
  4318. ''' </summary>
  4319. ''' <param name="scripts">Specifies the list of the scripts to be deleted.</param>
  4320. ''' <param name="nodes">Specifies the list of nodes on which scripts are deleted.</param>
  4321. ''' <returns></returns>
  4322. ''' <remarks></remarks>
  4323. Public Function SaveUserScripts(ByVal scripts As ScriptEntityCollection,
  4324. ByVal nodes As isr.Tsp.NodeEntityCollection) As Boolean
  4325. If scripts Is Nothing Then
  4326. Throw New ArgumentNullException("scripts")
  4327. End If
  4328. If nodes Is Nothing Then
  4329. Throw New ArgumentNullException("nodes")
  4330. End If
  4331. ' clear buffers before deleting.
  4332. Me._discardUnreadData(True)
  4333. Dim success As Boolean = True
  4334. For Each node As isr.Tsp.INodeEntity In nodes
  4335. success = success And SaveUserScripts(scripts, node)
  4336. Next
  4337. Return success
  4338. End Function
  4339. ''' <summary>
  4340. ''' Updates users scripts. Deletes out-dated scripts and loads and runs new scripts as required on all nodes.
  4341. ''' </summary>
  4342. ''' <param name="scripts">Specifies the list of the scripts to be deleted.</param>
  4343. ''' <param name="node">Specifies the node on which scripts are updated.</param>
  4344. ''' <param name="isSecondPass">Set true on the second pass through if first pass requires loading new scripts.</param>
  4345. ''' <returns></returns>
  4346. ''' <remarks></remarks>
  4347. Public Function UpdateUserScripts(ByVal scripts As ScriptEntityCollection,
  4348. ByVal node As INodeEntity, ByVal isSecondPass As Boolean) As Boolean
  4349. If scripts Is Nothing Then
  4350. Throw New ArgumentNullException("scripts")
  4351. End If
  4352. If node Is Nothing Then
  4353. Throw New ArgumentNullException("node")
  4354. End If
  4355. Dim synopsis As String = "Updating scripts"
  4356. Dim prefix As String = ""
  4357. If node.IsController Then
  4358. prefix = String.Format(Globalization.CultureInfo.CurrentCulture, "Instrument '{0}'", Me.ResourceName)
  4359. Else
  4360. prefix = String.Format(Globalization.CultureInfo.CurrentCulture, "Instrument '{0}' node #{1}", Me.ResourceName, node.Number)
  4361. End If
  4362. ' run scripts so that we can read their version numbers. Scripts will run only if not ran, namely
  4363. ' if there namespaces are not defined.
  4364. If Not scripts.RunScripts(node, Me) Then
  4365. ' report any failure.
  4366. If isSecondPass Then
  4367. Me.OnMessageAvailable(TraceEventType.Warning, synopsis,
  4368. "{0} failed running some firmware scripts because {1}.{2}{3}",
  4369. prefix, scripts.OutcomeDetails,
  4370. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4371. Return False
  4372. Else
  4373. Me.OnMessageAvailable(TraceEventType.Information, synopsis,
  4374. "{0} failed running some firmware scripts because {1}. Problem ignored.",
  4375. prefix, scripts.OutcomeDetails)
  4376. End If
  4377. End If
  4378. ' read scripts versions.
  4379. If Not scripts.ReadFirmwareVersions(node, Me) Then
  4380. If isSecondPass Then
  4381. ' report any failure.
  4382. Me.OnMessageAvailable(TraceEventType.Warning, synopsis,
  4383. " failed reading some firmware versions because {1}.{2}{3}",
  4384. prefix, scripts.OutcomeDetails,
  4385. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4386. Return False
  4387. Else
  4388. ' report any failure.
  4389. Me.OnMessageAvailable(TraceEventType.Information, synopsis,
  4390. " failed reading some firmware versions because {1}. Problem ignored.",
  4391. prefix, scripts.OutcomeDetails)
  4392. End If
  4393. End If
  4394. ' make sure program is up to date.
  4395. If Not isSecondPass AndAlso scripts.IsProgramOutdated(node) Then
  4396. Me.OnMessageAvailable(TraceEventType.Warning, synopsis,
  4397. "{0} program out of date because {1}. System initialization aborted.{2}{3}",
  4398. prefix, scripts.OutcomeDetails,
  4399. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4400. Return False
  4401. End If
  4402. If scripts.VersionsUnspecified(node) Then
  4403. If isSecondPass Then
  4404. Me.OnMessageAvailable(TraceEventType.Warning, synopsis,
  4405. "{0} failed verifying firmware version because because {1}.{2}{3}",
  4406. prefix, scripts.OutcomeDetails,
  4407. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4408. Return False
  4409. Else
  4410. Me.OnMessageAvailable(TraceEventType.Information, synopsis,
  4411. "{0} failed verifying firmware version because because {1}. Problem ignored.",
  4412. prefix, scripts.OutcomeDetails)
  4413. End If
  4414. End If
  4415. If scripts.AllVersionsCurrent(node) Then
  4416. Return True
  4417. ElseIf isSecondPass Then
  4418. If String.IsNullOrEmpty(scripts.OutcomeDetails) Then
  4419. Me.OnMessageAvailable(TraceEventType.Warning, synopsis,
  4420. "{0} failed updating scripts. Check log for details.{1}{2}",
  4421. prefix,
  4422. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4423. Else
  4424. Me.OnMessageAvailable(TraceEventType.Warning, synopsis, "{0} failed updating scripts because {1}.{2}{3}",
  4425. prefix,
  4426. scripts.OutcomeDetails,
  4427. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4428. End If
  4429. Return False
  4430. Else
  4431. isSecondPass = True
  4432. ' delete scripts that are out-dated or slated for deletion.
  4433. Me.OnMessageAvailable(TraceEventType.Verbose, synopsis, "{0} deleting out-dated scripts", prefix)
  4434. If Not Me.DeleteUserScripts(scripts, node, True, True) Then
  4435. Me.OnMessageAvailable(TraceEventType.Information, synopsis,
  4436. "{0} failed deleting out-dated scripts. Check log for details. Problem ignored.",
  4437. prefix)
  4438. End If
  4439. If LoadRunUserScripts(scripts, node) Then
  4440. Return Me.UpdateUserScripts(scripts, node, True)
  4441. Else
  4442. Me.OnMessageAvailable(TraceEventType.Warning, synopsis,
  4443. "{0} failed loading and/or running scripts. Check log for details.{1}{2}",
  4444. prefix,
  4445. Environment.NewLine, isr.Core.StackTraceParser.UserCallStack(4, 8))
  4446. Return False
  4447. End If
  4448. End If
  4449. End Function
  4450. ''' <summary>
  4451. ''' Updates users scripts deleting, as necessary, those that are out of date.
  4452. ''' </summary>
  4453. ''' <param name="scripts">Specifies the list of the scripts to be deleted.</param>
  4454. ''' <param name="nodes">Specifies the list of nodes on which scripts are deleted.</param>
  4455. ''' <returns></returns>
  4456. ''' <remarks></remarks>
  4457. Public Function UpdateUserScripts(ByVal scripts As ScriptEntityCollection,
  4458. ByVal nodes As isr.Tsp.NodeEntityCollection) As Boolean
  4459. If scripts Is Nothing Then
  4460. Throw New ArgumentNullException("scripts")
  4461. End If
  4462. If nodes Is Nothing Then
  4463. Throw New ArgumentNullException("nodes")
  4464. End If
  4465. ' clear buffers before deleting.
  4466. Me._discardUnreadData(True)
  4467. For Each node As isr.Tsp.INodeEntity In nodes
  4468. If Not UpdateUserScripts(scripts, node, False) Then
  4469. Return False
  4470. End If
  4471. Next
  4472. Return True
  4473. End Function
  4474. #End Region
  4475. #Region " TSPX: WRITE "
  4476. ''' <summary>
  4477. ''' Writes the script to file.
  4478. ''' </summary>
  4479. ''' <param name="folderPath">Specifies the script file folder</param>
  4480. ''' <param name="script">Specifies the script.</param>
  4481. ''' <param name="node">Specifies the node.</param>
  4482. ''' <param name="compress">Specifies the compression condition. True to compress the source before saving.</param>
  4483. ''' <returns></returns>
  4484. ''' <remarks></remarks>
  4485. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  4486. Public Function WriteScriptFile(ByVal folderPath As String, ByVal script As IScriptEntity,
  4487. ByVal node As INodeEntity, ByVal compress As Boolean) As Boolean Implements ITspInstrument.WriteScriptFile
  4488. If folderPath Is Nothing Then
  4489. Throw New ArgumentNullException("folderPath")
  4490. End If
  4491. If script Is Nothing Then
  4492. Throw New ArgumentNullException("script")
  4493. End If
  4494. If node Is Nothing Then
  4495. Throw New ArgumentNullException("node")
  4496. End If
  4497. Dim filePath As String = String.Format(Globalization.CultureInfo.CurrentCulture, "{0}.{1}",
  4498. script.FileName, node.ModelNumber)
  4499. filePath = System.IO.Path.Combine(folderPath, filePath)
  4500. Try
  4501. Using scriptFile As System.IO.StreamWriter = New System.IO.StreamWriter(filePath)
  4502. If scriptFile Is Nothing Then
  4503. ' now report the error to the calling module
  4504. Throw New BaseException("Failed opening TSP Script File '" & filePath & "'.")
  4505. End If
  4506. If Me.FetchScriptSource(script, node) Then
  4507. If compress Then
  4508. scriptFile.WriteLine("{0}{1}{2}", ScriptEntity.CompressedPrefix,
  4509. Me.LastFetchScriptSource.Compress(),
  4510. ScriptEntity.CompressedSuffix)
  4511. Else
  4512. scriptFile.WriteLine(Me.LastFetchScriptSource)
  4513. End If
  4514. Return True
  4515. Else
  4516. Return False
  4517. End If
  4518. End Using
  4519. Catch
  4520. ' clear receive buffer.
  4521. Me._discardUnreadData(False)
  4522. Throw
  4523. Finally
  4524. End Try
  4525. End Function
  4526. ''' <summary>
  4527. ''' Writes the script to file.
  4528. ''' </summary>
  4529. ''' <param name="folderPath">Specifies the script file folder</param>
  4530. ''' <param name="scripts">Specifies the scripts.</param>
  4531. ''' <param name="nodes">Specifies the nodes.</param>
  4532. ''' <returns></returns>
  4533. ''' <remarks></remarks>
  4534. <CodeAnalysis.SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")>
  4535. Public Function WriteScriptFiles(ByVal folderPath As String,
  4536. ByVal scripts As isr.Tsp.ScriptEntityCollection,
  4537. ByVal nodes As isr.Tsp.NodeEntityCollection) As Boolean
  4538. If folderPath Is Nothing Then
  4539. Throw New ArgumentNullException("folderPath")
  4540. End If
  4541. If scripts Is Nothing Then
  4542. Throw New ArgumentNullException("scripts")
  4543. End If
  4544. If nodes Is Nothing Then
  4545. Throw New ArgumentNullException("nodes")
  4546. End If
  4547. ' clear receive buffer.
  4548. Me._discardUnreadData(False)
  4549. Dim success As Boolean = True
  4550. For Each node As isr.Tsp.INodeEntity In nodes
  4551. For Each script As isr.Tsp.IScriptEntity In scripts
  4552. ' do not save the script if is has no file name. Future upgrade might suggest adding a file name to the boot script.
  4553. If script.IsModelMatch(node.ModelNumber) AndAlso Not String.IsNullOrEmpty(script.FileName) AndAlso Not script.SavedToFile Then
  4554. Me.DisplayLine(2, "Writing {0}:{1}", node.ModelNumber, script.Name)
  4555. If Me.WriteScriptFile(folderPath, script, node, ((script.FileFormat And ScriptFileFormats.Compressed) <> 0)) Then
  4556. script.SavedToFile = True
  4557. success = success AndAlso True
  4558. Else
  4559. success = False
  4560. End If
  4561. End If
  4562. Next
  4563. Next
  4564. Return success
  4565. End Function
  4566. #End Region
  4567. #Region " TSP: SYNTAX "
  4568. ''' <summary>
  4569. ''' Checks the series of values and return true if any one of them is nil.
  4570. ''' </summary>
  4571. ''' <param name="values">Specifies a list of nil objects to check.</param>
  4572. ''' <returns></returns>
  4573. ''' <remarks></remarks>
  4574. Public Function IsNil(ByVal ParamArray values() As String) As Boolean Implements ITspInstrument.IsNil
  4575. If values Is Nothing OrElse values.Length = 0 Then
  4576. Throw New ArgumentNullException("values")
  4577. Else
  4578. For Each value As String In values
  4579. If Not String.IsNullOrEmpty(value) Then
  4580. If Me.IsStatementTrue("{0} == nil", value) Then
  4581. Return True
  4582. End If
  4583. End If
  4584. Next
  4585. End If
  4586. Return False
  4587. End Function
  4588. ''' <summary>
  4589. ''' Returns true if the validation command returns true.
  4590. ''' </summary>
  4591. ''' <param name="format">Specifies the format statement for constructing the assertion.</param>
  4592. ''' <param name="args">Specifies the arguments to use when formatting the assertion.</param>
  4593. ''' <returns></returns>
  4594. ''' <remarks></remarks>
  4595. Public Function IsStatementTrue(ByVal format As String, ByVal ParamArray args() As Object) As Boolean Implements ITspInstrument.IsStatementTrue
  4596. If String.IsNullOrEmpty(format) Then
  4597. Throw New ArgumentNullException("format")
  4598. End If
  4599. Dim outcome As Boolean? = MyBase.QueryBoolean("print({0}) waitcomplete()", String.Format(Globalization.CultureInfo.InvariantCulture, format, args))
  4600. Return outcome.HasValue AndAlso outcome.Value
  4601. End Function
  4602. ''' <summary>
  4603. ''' Sends a print command to the instrument using the specified format and arguments.
  4604. ''' The format conforms to the 'C' query command and returns the Boolean outcome.
  4605. ''' </summary>
  4606. ''' <param name="format">Specifies the format statement</param>
  4607. ''' <param name="args">Specifies the arguments to use when formatting the command.</param>
  4608. ''' <returns></returns>
  4609. ''' <remarks>
  4610. ''' The format string follows the same rules as the printf family of standard C functions.
  4611. ''' The only differences are that the options or modifiers *, l, L, n, p, and h are not
  4612. ''' supported and that there is an extra option, q. The q option formats a string in a
  4613. ''' form suitable to be safely read back by the Lua interpreter: the string is written
  4614. ''' between double quotes, and all double quotes, newlines, embedded zeros, and backslashes
  4615. ''' in the string are correctly escaped when written. For instance, the
  4616. ''' call string.format('%q', 'a string with ''quotes'' and [BS]n new line') will produce the string:
  4617. ''' a string with [BS]''quotes[BS]'' and [BS]new line
  4618. ''' The options c, d, E, e, f, g, G, i, o, u, X, and x all expect a number as argument,
  4619. ''' whereas q and s expect a string. This function does not accept string values containing embedded zeros.
  4620. ''' </remarks>
  4621. Public Function QueryPrintFormat(ByVal format As String, ByVal ParamArray args() As String) As String Implements ITspInstrument.QueryPrintFormat
  4622. If MyBase.WriteQueryLine("print(string.format('{0}',{1}))", format, isr.Tsp.TspScript.Parameterize(args)) Then
  4623. If Me.RaiseVisaOrDeviceException("failed query " & format, args) Then
  4624. Return MyBase.ReadLineTrimEnd()
  4625. Else
  4626. Return ""
  4627. End If
  4628. Else
  4629. Return ""
  4630. End If
  4631. End Function
  4632. #End Region
  4633. End Class