WinCC

 

E' possibile trasmettere segnali a Databoom utilizzando piattaforme per la supervisione ed il controllo industriali facenti uso della tecnologia software HMI/Scada, quale WinCC.

L'invio dei dati è implementato attraverso la stesura di codice VBScript.

 


 

Prerequisiti

Per poter eseguire correttamente lo script, è necessario l'utilizzo di curl. E' possibile verificarne la presenza aprendo una linea di comando e lanciando il comando stesso. Se non installato sul proprio sistema, recuperare l'eseguibile opportuno dalla pagina di download del sito cURL.

E' necessario annotare il percorso completo dell'eseguibile (curl.exe) per poterlo utilizzare nello script.

 


 

VBScript

Lo script è strutturato in due parti:

  • Loop, si occupa dell'esecuzione ciclica dello script
  • Handlers, gestisce eventuali errori durante l'esecuzione

A seconda della versione di WinCC utilizzata sarà possibile creare solo due script VBscript corrispondenti a Loop e Handlers o creare uno script per ogni funzione (in particolar modo la parte di Handlers è costituita da 6 funzioni).


Funzioni VBScript su WinCC V14 SP1

La parte di Loop contiene un ciclo Do While True che potrebbe creare problemi nella visualizzazione delle pagine (segnalazione ricevuta nell'utilizzo su WinCC V14 SP1), in tal caso è possibile ripetere l'esecuzione dello script utilizzando la funzionalità di schedulazione.


La funzione PostDataboom assegnata ad uno scheduler per l'esecuzione ogni minuto

Loop
 Sub PostDataboom()
	Dim prev, apiClock, apiPost, apiKey, curl, curlGet, jsonEmpty

	'File di log per tutte le variabili
	Dim logs<SIGNAL_1>
	Dim logs<SIGNAL_2>

	Dim logError 'memorizza tutti gli errori 
	Dim logBulk 'memorizza il post prima dell'inoltro in caso di bulk
	Dim resultPost
	Dim resultDate
	Dim resultBulk
	
	prev = -1
	apiClock = "https://api.databoom.com/v1/auth/gmtclock/plain"	
	apiPost = "https://api.databoom.com/v1/signals/push"
	apiKey = "<USER_API_KEY>"
	curl = "cmd /C <CURL_FULL_PATH> --header ""apikey: " & apiKey & """" & " --header ""Content-Type: application/json"" -X POST -d """ 
	curlGet = "cmd /C <CURL_FULL_PATH> -X GET " 
	jsonEmpty = "{\""MSG\"":\""OK\""}"

	'Definisco i percorsi dei file di log
 	logs<SIGNAL_1> = "<LOGS_DIR_FULL_PATH>\<SIGNAL_1>.txt"
	logs<SIGNAL_2> = "<LOGS_DIR_FULL_PATH>\<SIGNAL_2> .txt"

	logError = "<LOGS_DIR_FULL_PATH>\ERRORS.txt"
	logBulk = "<LOGS_DIR_FULL_PATH>\bulkToPost.txt"
	resultPost = "<LOGS_DIR_FULL_PATH>\resultPost.txt"
	resultDate = "<LOGS_DIR_FULL_PATH>\resultDate.txt"
	resultBulk = "<LOGS_DIR_FULL_PATH>\resultBulk.txt"
	
	Do While True	
		If (Minute(Now) <> prev) And (Minute(Now) Mod 5 = 0) Then	
		    Dim sDate, postResult, bulkResult, JSONString, canConn, FSO, TS
			Const ForReading = 1, ForWriting = 2, ForAppending = 8 
			Set FSO = CreateObject("Scripting.FileSystemObject")
			'Verifica la presenza dei file di log, li genera se non li trova
			On Error Resume Next
				Set TS = FSO.OpenTextFile(logs<SIGNAL_1>, ForAppending, True)
				TS.Close 
				Set TS = FSO.OpenTextFile(logs<SIGNAL_2>, ForAppending, True)
				TS.Close 				
			If Err.Number <> 0 Then
				storeError logError, Err, "Can't create log file"
			    Err.Clear
			End If
							
			canConn = True	
			sDate = ""
			postResult = ""
			bulkResult = ""
			
			Dim objWshShell, result
			Set objWshShell = CreateObject("Wscript.Shell")
					
			On Error Resume Next	
				'objWshShell.run curl & jsonEmpty & """ " & apiClock & "  > " & resultDate, 0, True
				objWshShell.Run curlGet & apiClock & "  > " & resultDate, 0, True
			If Err.Number <> 0 Then
				storeError logError, Err, "Can't curl date"
				Err.Clear
			End If 		
			
			Set result = FSO.OpenTextFile(resultDate, ForReading)
			sDate = result.ReadAll
			result.Close	
			
			If Len(sDate) <> 21 Then
				HandleDateRequest canConn,sDate				
				Set TS = FSO.OpenTextFile(logError, ForAppending)
				TS.Write ((Year(Now)*100 + Month(Now))*100 + Day(Now))*10000 + Hour(Now)*100 + Minute(Now) & " - ERROR: Can't retrieve date: " & sDate & vbCrLf
				TS.Close
			End If					
			

			'Definisco le variabili per la lettura dei dati
			Dim <SIGNAL_1>
			Dim <SIGNAL_2>

			'Assegno alle variabili quelle di WinCC
			Set <SIGNAL_1>= SmartTags("<SIGNAL_1_WINCC_VAR>") 'A seconda della versione utilizzare SmartTags() o HMIRuntime.Tags()
			Set <SIGNAL_2>= SmartTags("<SIGNAL_2_WINCC_VAR>")

			JSONString = "{\""device\"":\""<DATABOOM_DEVICE_TOKEN>\"",\""date\"":\""" & sDate & "\"", \""signals\"":["
			JSONString = JSONString & "{\""name\"":\""<DATABOOM_SIGNAL_1_TOKEN>\"",\""value\"":"& Replace(<SIGNAL_1>,",",".") & "}," 'nel caso di utilizzo di HMIRuntime.Tags(), utilizzare .Read(1) per la lettura dei valori delle variabili
			JSONString = JSONString & "{\""name\"":\""<DATABOOM_SIGNAL_2_TOKEN>\"",\""value\"":"& Replace(<SIGNAL_2>,",",".") & "}"
			JSONString = JSONString & "]}"
			
			On Error Resume Next
				objWshShell.Run curl & JSONString & """ " & apiPost & "  > " & resultPost, 0, True
			If Err.Number <> 0 Then
				storeError logError, Err, "Can't curl post, " & JSONString
				Err.Clear
			End If 		
			
			Set result = FSO.OpenTextFile(resultPost, ForReading)
			postResult = result.ReadAll
			result.Close	
			
			If postResult <> "{""message"":""ALL_INFO_PROCESSED""}" Then
				HandleFailedPost canConn, FSO, TS, sDate, Replace(<SIGNAL_1>,",","."), logs<SIGNAL_1>
				HandleFailedPost canConn, FSO, TS, sDate, Replace(<SIGNAL_2>,",","."), logs<SIGNAL_2>
			
				Set TS = FSO.OpenTextFile(logError, ForAppending)
				TS.Write ((Year(Now)*100 + Month(Now))*100 + Day(Now))*10000 + Hour(Now)*100 + Minute(Now) & " - ERROR: Can't send post " & postResult & vbCrLf
				TS.Close
			End If					
			
			If canConn = True Then
				Dim bulk, emptyBulk
				emptyBulk = True
				bulk = "{""device"":""<DATABOOM_DEVICE_TOKEN>"",""date"":" & sDate & ", ""signals"":{"

				'Per ogni segnale aggiungo i dati raccolti nei rispettivi bulk
  				bulk = bulk & " ""<DATABOOM_SIGNAL_1_TOKEN>"" : {""description"":""<DATABOOM_SIGNAL_1_TOKEN>"", ""history"":["
  				addHistory logs<SIGNAL_1>, bulk 				
				If StrComp(Right(bulk, 1),",") = 0 Then
					bulk = Left(bulk, Len(bulk) - 1) & "]},"
					emptyBulk = False
				Else
					bulk = bulk & "]},"
				End If

				bulk = bulk & " ""<DATABOOM_SIGNAL_2_TOKEN>"" : {""description"":""DATABOOM_SIGNAL_2_TOKEN>"", ""history"":["
  				addHistory logs<SIGNAL_2>, bulk 				
				If StrComp(Right(bulk, 1),",") = 0 Then
					bulk = Left(bulk, Len(bulk) - 1) & "]}}}"
					emptyBulk = False
				Else
					bulk = bulk & "]}}}"
				End If										

  				If emptyBulk = False Then	
  					On Error Resume Next 
	  					Set TS = FSO.OpenTextFile(logBulk, ForWriting)
						TS.Write bulk
						TS.Close										
  					If Err.Number <> 0 Then
						storeError logError, Err, "Can't log bulk"
					    Err.Clear
					End If 		
						
  					On Error Resume Next  						
  						objWshShell.Run curl & "@" & logBulk & """ " & apiPost & "  > " & resultBulk, 0, True 								
  					If Err.Number <> 0 Then
						storeError logError, Err, "Can't run bulk curl"
					    Err.Clear
					End If 		
  								
					Set result = FSO.OpenTextFile(resultBulk, ForReading)
					bulkResult = result.ReadAll
					result.Close	
					
					If bulkResult <> "{""message"":""ALL_INFO_PROCESSED""}" Then	
						HandleFailedConn canConn		
						Set TS = FSO.OpenTextFile(logError, ForAppending)
						TS.Write ((Year(Now)*100 + Month(Now))*100 + Day(Now))*10000 + Hour(Now)*100 + Minute(Now) & " - ERROR: Can't send bulk " & bulkResult & vbCrLf & bulk & vbCrLf
						TS.Close
					End If

   					If canConn = True Then
    					cleanHistory logsPotenza
						cleanHistory logs<SIGNAL_1>
						cleanHistory logs<SIGNAL_2>
   					End If
  				End If
 			End If
		
			FSO.DeleteFile(logBulk)
			FSO.DeleteFile(resultPost)
			FSO.DeleteFile(resultDate)
			FSO.DeleteFile(resultBulk)
			
			Set TS = Nothing
			Set FSO = Nothing
			prev = Minute(Now)
		End If	
	Loop	
End Sub
  
In grassetto corsivo sono indicati i campi che vanno sostituiti in base alle esigenze dell'utente.

logs<SIGNAL 1> e logs<SIGNAL 2> sono i file di logging, verranno creati se inesistenti. Le directory specificate con gli indirizzi completi <LOGS_DIR_FULL_PATH> devono essere esistenti.

ATTENZIONE! Assicurarsi che le directory siano esistenti altrimenti lo script non sarà in grado di creare i file e funzionare correttamente.

Nell'esempio sono rappresentate due tag, è possibile aggiungerne altre seguendo la stessa procedura.

ATTENZIONE! Quando si aggiungono nuove variabili, controllare sempre le parentesi di chiusura. L'ultima variabile non deve avere virgole alla fine, come <Signal 2> nell'esempio, mentre le altre variabili devono rispecchiare <Signal 1>.

Handlers
Sub addHistory(ByVal logFile, ByRef bulk)
  Const ForReading = 1
  Dim FSO, TS
  Set FSO = CreateObject("Scripting.FileSystemObject")
  Set TS = FSO.OpenTextFile(logFile, ForReading)
  Do Until TS.AtEndOfStream
   bulk = bulk & TS.ReadLine & ","
  Loop
  TS.Close
End Sub
Sub cleanHistory(ByVal logFile)
  Const ForWriting = 2
  Dim FSO, TS
  Set FSO = CreateObject("Scripting.FileSystemObject")
  Set TS = FSO.OpenTextFile(logFile, ForWriting, True)
  TS.Write ""
  TS.Close
End Sub
Sub HandleDateRequest(ByRef canConn, ByRef sDate)
	canConn = False	
	sDate = Year(Date) & "-" & Right(String(2, "0") & Month(Date), 2) & "-" & Right(String(2, "0") & Day(Date), 2) & "T" & Right(String(2, "0") & Hour(Now), 2) & ":" & Right(String(2, "0") & Minute(Now), 2) & ":" & Right(String(2, "0") & Second (Now), 2)
End Sub
Sub HandleFailedConn(ByRef canConn)
	canConn = False
End Sub
Sub HandleFailedPost(ByRef canConn, ByRef FSO, ByRef TS, ByVal sDate, ByVal variable, ByVal logsVariable)
	Const ForAppending = 8 
	canConn = False

	Set TS = FSO.OpenTextFile(logsVariable, ForAppending, True)
	TS.Write "{""date"":"""& sDate &""",""value"":"& variable &"}" & vbCrLf
	TS.Close
End Sub
Sub storeError(ByVal logError, ByRef errData, ByRef errExtra)
  Const ForAppending = 8 
  Dim FSO, TS
  Set FSO = CreateObject("Scripting.FileSystemObject")
  Set TS = FSO.OpenTextFile(logError, ForAppending, True)
  TS.Write ((Year(Now)*100 + Month(Now))*100 + Day(Now))*10000 + Hour(Now)*100 + Minute(Now) & " - Error: [" & Err.Number &  ", "& Err.Source &", "& Err.Description & "] "& errExtra & vbCrLf
  TS.Close
End Sub
 

 


 

Esecuzione dello script

Una volta inseriti gli script in WinCC, è possibile iniziare la registrazione dei dati in Databoom.
Uno dei possibili approcci è quello di chiamare la funzione principale all'apertura della finestra principale del proprio progetto.

Aprire la funzionalità di Graphics Designer dal menù laterale, quindi accedere alla finestra principale <NOME>.PDL . Cliccare con il tasto destro del mouse sul livello di base e scegliere il menù Proprietà. Posizionarsi quindi sulla scheda Evento e seguire Oggetto della Pagina -> Varie -> Seleziona pagina ed infine Azione VBS...

Azione VBS

La porzione di codice da inserire sarà la chiamata al codice precedente

Sub OnOpen()
  PostDataboom
End Sub

 


Esecuzione script su WinCC V14 SP1

 


 

Configurazione completata!

Una volta completata la procedura, Databoom inizierà a registrare i dati inviati da WinCC. Per poter consultare i dati e avere una rappresentazione corretta, seguire le indicazioni in Modifica/validazione di un segnale.

 


 

Progetto d'esempio

In allegato all'articolo è disponibile un progetto per TIA Portal V14, contenente un esempio funzionante di trasmissione tag a Databoom.

E' sufficiente completare lo script inserendola propria api key e il token del proprio dispositivo dove indicato (all'interno della funzione VB PostDataboom).

Altre domande? Invia una richiesta

0 Commenti

Accedi per aggiungere un commento.