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 uno script 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.

VBScript

Lo script è strutturato in due parti:

  • Loop, si occupa dell'esecuzione ciclica dello script
  • Handlers, gestisce eventuali errori durante l'esecuzione
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 'memorizza temporaneamente la risposta delle post request
    Dim resultDate 'memorizza temporaneamente la risposta delle date request
    Dim resultBulk 'memorizza temporaneamente la risposta delle bulk request
    
    prev = -1
    apiClock = "https://api.databoom.com/v1/auth/gmtclock/plain"    
    apiPost = "https://api.databoom.com/v1/signals/push"
    apiKey = "<API KEY DATABOOM>"
    curl = "cmd /C <PATH COMPLETO>\curl.exe --header ""apikey: " & apiKey & """" & " --header ""Content-Type: application/json"" -X POST -d """
   curlGet = "cmd /C <PATH COMPLETO>\curl.exe -X GET "
    jsonEmpty = "{\""MSG\"":\""OK\""}"

    'Definisco i percorsi dei file di log
    logs<SIGNAL 1> = "<PATH COMPLETO>\<SIGNAL 1>.txt"
    logs<SIGNAL 2> = "<PATH COMPLETO>\<SIGNAL 2>.txt"

    logError = "<PATH COMPLETO>\ERRORS.txt"
    logBulk = "<PATH COMPLETO>\bulkToPost.txt"
    resultPost = "<PATH COMPLETO>\resultPost.txt"
    resultDate = "<PATH COMPLETO>\resultDate.txt"
    resultBulk = "<PATH COMPLETO>\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 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" & 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> = HMIRuntime.Tags("<SIGNAL 1>")
            Set <SIGNAL 2> = HMIRuntime.Tags("<SIGNAL 2>")

            JSONString = "{\""device\"":\""<DEVICE TOKEN>\"",\""date\"":\""" & sDate & "\"", \""signals\"":["
            JSONString = JSONString & "{\""name\"":\""<SIGNAL 1>\"",\""value\"":"& Replace(pressioneCondottaForzata.Read(1),",",".") & "},"
            JSONString = JSONString & "{\""name\"":\""<SIGNAL 2>\"",\""value\"":"& Replace(portataCondotta.Read(1),",",".") & "}"
            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>.Read(1),",","."), logs<SIGNAL 1>
                HandleFailedPost canConn, FSO, TS, sDate, Replace(<SIGNAL 2>.Read(1),",","."), 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"":""<DEVICE TOKEN>"",""Date"":""" & sDate & """, ""signals"":{"

                'Per ogni segnale aggiungo i dati raccolti nei rispettivi bulk
                  bulk = bulk & " ""<SIGNAL 1>"" : {""description"":""<SIGNAL 1>"", ""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 & " ""<SIGNAL 2>"" : {""description"":""<SIGNAL 2>"", ""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 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

logs<SIGNAL 1> e logs<SIGNAL 2> sono i file di logging, verranno creati se inesistenti. Le directory specificate con gli indirizzi completi <PATH COMPLETO> 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
 
Const ForReading = 1, ForWriting = 2, ForAppending = 8

Sub    HandleFailedConn(Byref canConn)
    canConn = False
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 HandleFailedPost(Byref canConn, Byref FSO, Byref TS, Byval sDate, Byval variable, Byval logsVariable)
    canConn = False

    Set TS = FSO.OpenTextFile(logsVariable, ForAppending, True)
    TS.Write "{""date"":"""& sDate &""",""value"":"& variable &"}" & vbCrLf
    TS.Close

    JSONString = ""
End Sub

Sub addHistory(ByVal logFile, ByRef bulk)
  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)
  Dim FSO, TS
  Set FSO = CreateObject("Scripting.FileSystemObject")
  Set TS = FSO.OpenTextFile(logFile, ForWriting, True)
  TS.Write ""
  TS.Close
End Sub

Sub storeError(Byval logError, Byref Err, Byval errExtra)
  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

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.

Altre domande? Invia una richiesta

0 Commenti

Accedi per aggiungere un commento.