Pulsa ESC para cerrar · Ctrl+K para abrir

WinCC v8.1 Leer Alarmas

WinCC v8.1 Leer Alarmas

El objetivo es desde la sala de control poder escuchar el mensaje de ciertas alarmas catalogadas como críticas

Por defecto WinCC no tiene esta funcionalidad, y es lo que vamos a agregar, vamos a crear una librería en C++ para darle esta funcionalidad.

El código de nuestra función es el siguiente, y si quieres crear tu propia librería aquí escribi un artículo hace ya unos años ;-)

Cpp
Codigo
#include <sapi.h>
#include <string>
#include <stdio.h>
#include <stdlib.h>
#include <codecvt>

extern "C"
{
    __declspec(dllexport) void SpeakText(char* input);
}

__declspec(dllexport) void SpeakText(char* input)
{
    // Initialize COM
    HRESULT hr = ::CoInitialize(NULL);
    if (FAILED(hr)) return;

    ISpVoice* pVoice = NULL;

    // Create voice instance
    hr = CoCreateInstance(CLSID_SpVoice, NULL, CLSCTX_ALL, IID_ISpVoice, (void**)&pVoice);
    if (SUCCEEDED(hr)) {
        // Convert char* to std::wstring
        std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;
        std::wstring wtext = converter.from_bytes(input);

        // Speak the text
        pVoice->Speak(wtext.c_str(), SPF_IS_XML, NULL);
        pVoice->Release();
    }

    ::CoUninitialize();
}


Una vez que ya tenemos nuestra librería compilada, vamos a adaptar la función GMsgFunct con el siguiente código

Cpp
Codigo
BOOL GMsgFunction( char* pszMsgData)
{

#pragma code("C:/Controls/PHSSpeechSynth.dll")
void SpeakText(char* input);
#pragma code()

BOOL bOK;
WORD wTextBlock = 0;
DWORD dwTextNr = 34 ;
MSG_TEXT_STRUCT scMsgText;
CMN_ERROR scError;
MSG_CSDATA_STRUCT sM; 
CMN_ERROR pError;

MSG_RTDATA_STRUCT mRT;
memset( &mRT, 0, sizeof( MSG_RTDATA_STRUCT ) );

if( pszMsgData != NULL )
  {
     printf( "Meldung : %s 
", pszMsgData );

    // Meldungsdaten einlesen
     sscanf( pszMsgData,  "%ld,%ld,%04d.%02d.%02d,%02d:%02d:%02d:%03d,%ld, %ld, %ld, %d,%d",
	&mRT.dwMsgNr, 			// Meldungsnummer
	&mRT.dwMsgState,  			// Status MSG_STATE_COME, .._GO, .._QUIT, .._QUIT_SYSTEM
	&mRT.stMsgTime.wYear, 		// Jahr
	&mRT.stMsgTime.wMonth, 		// Monat
	&mRT.stMsgTime.wDay,		// Tag
	&mRT.stMsgTime.wHour, 		// Stunde
	&mRT.stMsgTime.wMinute,		// Minute
	&mRT.stMsgTime.wSecond, 		// Sekunde
	&mRT.stMsgTime.wMilliseconds,	// Millisekunde
	&mRT.dwTimeDiff,			// Zeitdauer der anstehenden Meldung
	&mRT.dwCounter,			// Interner Meldungszähler
	&mRT.dwFlags,			// Flags( intern )
	&mRT.wPValueUsed,
	&mRT.wTextValueUsed );
 
      // Prozesswerte lesen, falls gewünscht
    } 

  printf("Nr : %d, St: %x, %d-%d-%d %d:%d:%d.%d, Dur: %d, Cnt %d, Fl %d
" , 
  mRT.dwMsgNr, mRT.dwMsgState, mRT.stMsgTime.wDay, mRT.stMsgTime.wMonth, mRT.stMsgTime.wYear, 
  mRT.stMsgTime.wHour, mRT.stMsgTime.wMinute, mRT.stMsgTime.wSecond, mRT.stMsgTime.wMilliseconds, mRT.dwTimeDiff,
  mRT.dwCounter, mRT.dwFlags ) ;

// Add this function to get information
  MSRTGetMsgCSData(mRT.dwMsgNr, &sM, &pError); 
  printf ("MSRTGetMsgCSData() - szText=\"%i\"
", sM.dwTextID[0]);

  // Retrieve the message text
  bOK = MSRTGetMsgText(wTextBlock, sM.dwTextID[0], &scMsgText, &scError );
  if (bOK)
  {
  	printf ("MSRTGetMsgText() - szText=\"%s\"
", scMsgText.szText);
	SpeakText(scMsgText.szText);
  }

  return( TRUE );
}


La parte mas importante es la declaración de la función de nuestra librería


El siguiente paso es habilitar Triggers action, Loop in Alarm a las alarmas que nos interesan con la función que hayamos definido


Y ahora activa los altavoces para comprobar su funcionamiento... ;-)

Dedicado a mi buen compañero Rafael Hernández Martínez por las lecciones sobre DCS particularmente DeltaV.

Cuando trabajas en equipo y compartes, lo único que puede pasar es que te beneficies ;-)

Descargar la librería