• Nenhum resultado encontrado

Relatório Final. Implementação do Conversor de Protocolos

N/A
N/A
Protected

Academic year: 2022

Share "Relatório Final. Implementação do Conversor de Protocolos"

Copied!
28
0
0

Texto

(1)

P&D 068 - Programa de P&D da ANEEL

Desenvolvimento de software conversor de protocolos para integração de equipamentos de proteção, controle, supervisão e automação de subestações

Relatório Final

Implementação do Conversor de Protocolos

Equipe DEE/UFMG :

Professores: Renato Cardoso Mesquita (Coordenador) Flávio Henrique Vasconcelos

Alunos: Edilson Santana de Souza Eduardo José da Silva Luz

Rodrigo Pereira Campana Benedito

Departamento de Engenharia Elétrica Universidade Federal de Minas Gerais

30 de Junho de 2006

(2)

1. Introdução

Este relatório se refere às atividades desenvolvidas no projeto P&D 068 da ANEEL intitulado “Desenvolvimento de Software Conversor de Protocolos para Integração de equipamentos de proteção, controle, supervisão e automação de subestações”, desenvolvido em parceria estabelecida entre a CEMIG e a UFMG.

O conversor de protocolos é um software executado em um PC efetuando a comunicação com os vários dispositivos presentes na subestação (UTRs, Medidores Inteligentes, Relés de Proteção, IEDs ) e também com o Centro de Controle. A conversão entre os protocolos é efetuada a partir de uma base de dados comum, acessível por todos os protocolos, e gerenciada pelo conversor. Este banco de dados também é acessível por outros programas, de modo que a implementação de outras funcionalidades, como automatismos e IHM, seja facilitada. A implementação dos protocolos foi efetuada de maneira gradual, se iniciando com o protocolo MODBUS RTU Master [1], seguida pela camada de enlace de dados do protocolo DNP3 master [2], da camada de aplicativo do mesmo protocolo [3] e, finalmente, do protocolo DNP3 slave.

Neste relatório serão apresentadas as características mais importantes da arquitetura do conversor de protocolos, alguns detalhes de sua implementação e as principais características dos protocolos implementados. Maiores detalhes são apresentados na documentação que acompanha este relatório [8, 9].

A figura 1 mostra a arquitetura do sistema no qual será inserido o conversor de protocolos:

Figura 1: Arquitetura do sistema no qual será inserido o conversor de protocolos O conversor de protocolos é um software executado em um PC efetuando a comunicação com os vários dispositivos presentes na subestação (UTRs, Medidores Inteligentes, Relés de Proteção, IEDs ) e também com o Centro de Controle. A conversão entre os protocolos é efetuada a partir de uma base de dados comum, acessível por todos os protocolos, e gerenciada pelo conversor. Este banco de dados também é acessível por outros programas, de modo que a implementação de outras funcionalidades, como automatismos e IHM, seja facilitada. A implementação dos protocolos está sendo efetuada de maneira gradual, se iniciando com o protocolo MODBUS RTU Master, em linha serial, que apresentaremos resumidamente, a seguir.

Figura 1: Arquitetura do sistema onde será inserido o conversor de protocolos CONVERSOR DE

PROTOCOLOS

MEDIDOR

INTELIGENTE RELÉ DE

PROTEÇÃO

UTR IED

CENTRO DE CONTROLE Protocolos:

- Modbus RTU - DNP 3.0 - Protocolo

para rede ethernet

Protocolos:

- DNP 3.0 -TCP/IP

Funcionalidades adicionais:

- Registros históricos - Automatismos - IHM

(3)

2. O Protocolo Modbus

O objetivo desta seção não é apresentar todos os detalhes do protocolo Modbus, mas apenas a informação necessária para se entender a sua implementação. Maiores detalhes podem ser consultados nas referências [16] e [17].

O Modbus foi desenvolvido pela Modicon Industrial Automation Systems, hoje Schneider Automation, para efetuar a comunicação entre um dispositivo mestre e outros dispositivos escravos. É um dos protocolos de mais larga utilização em automação industrial.

O protocolo está situado na camada de aplicação do modelo OSI (nível 7), sendo atualmente implementado para uso com TCP/IP sobre Ethernet, comunicação serial assíncrona nos padrões EIA/TIA-232-E (RS-232), EIA-422, EIA/TIA-485-A (RS-485), fibra ótica e rádio. Isto permite que variados tipos de arquitetura de redes com diferentes tipos de dispositivos (PLC, IHM, Painel de Controle, Driver, Dispositivo de Entrada/Saída) funcionem, integradamente, em um mesmo sistema.

A comunicação se dá no formato “requisição/resposta”, com os serviços ofertados pelo protocolo especificados por códigos de função. Estas funções se agregam a estruturas denominadas PDUs (Protocol Data Units). As PDUs são compostas por dois campos, conforme mostra a figura 2: o primeiro, denominado Function Code, é destinado ao código de função que representará a ação a ser executada pelo escravo. Este código ocupa 1 byte na PDU, com valor podendo variar de 1 a 255. Entretanto, os valores de 128 a 255 são reservados para respostas a exceções. O segundo campo, denominado Data, quando enviado do mestre para um escravo (PDU de requisição), contém informações adicionais que o dispositivo utilizará para executar uma ação definida no código de função. Códigos relativos a sub-funções podem também ser acrescidos neste campo. O campo Data pode ter comprimento de zero a 252 bytes (comunicação serial), dependendo da função utilizada (Figura 2.).

Figura 2: Frame genérico Modbus

No caso de uma PDU de resposta, enviada de um escravo para o mestre, se houver sucesso na execução da função, o primeiro campo (Function Code) retornará a mesma função recebida do mestre e o segundo (Data) conterá as informações desejadas pela PDU de requisição. Se houver fracasso, o primeiro campo retornará o código de função com o bit mais significativo (MSB) no estado 1 e o campo Data com códigos de exceções que deverão ser tratados pelo mestre. Esta mensagem denomina-se PDU de resposta de exceções. Além dos campos da PDU, existem campos adicionais que são utilizados para mapeamento do protocolo Modbus em barramentos ou redes específicas. Estes campos somados aos campos da PDU compõem a Application Data Unity (ADU). O campo Additional Adress tem 1 byte de comprimento e o Error Check, dois bytes, pois comporta checagem de erro por LRC (Longitudinal Redundancy Check) e CRC (Cyclical Redundancy

(4)

Check) (Figura 2). A ADU completa possui no máximo 256 bytes para comunicação serial e em TCP/IP.

O modelo de dados Modbus é baseado em tabelas que diferenciam os tipos de entradas e saídas referenciadas, conforme a tabela 1.

Tabela 1: Entradas e saídas no protocolo Modbus.

Cada uma destas entradas e saídas está localizada na memória do dispositivo. Deve-se ressaltar que o endereço utilizado pelo protocolo para referenciar a variável não é o mesmo da memória física do dispositivo. É necessário, portanto, mapear-se um no outro, o que é dependente do dispositivo (maiores detalhes em [16]).

Com relação às funções implementadas pelo protocolo, existem três categorias:

Public Function Codes: são as funções publicamente documentadas.

User-Defined Function Codes: funções definidas pelo usuário sem a aprovação da modbus.org.

Reserved Function Codes: funções utilizadas por algumas empresas, por questão de compatibilidade com produtos antigos.

As funções públicas do protocolo Modbus podem ser encontradas na tabela 2, e são as únicas implementadas neste projeto. Para maiores detalhes, ver [16].

Tabela 2: Funções públicas do protocolo Modbus.

(5)

3. O Protocolo DNP3

O objetivo desta seção não é apresentar todos os detalhes do protocolo DNP3, mas apenas as informações necessárias para entender a sua implementação. Maiores detalhes podem ser obtidos nas referência [2, 3, 4, 5, 6 e 7]. O DNP3 é , essencialmente, utilizado em sistemas SCADA e de automação distribuída. Ele é um protocolo não proprietário, desenvolvido pelo DNP Users Group, para atingir as seguintes metas:

1. Alta integridade de dados: a camada de enlace de dados do DNP3 utiliza uma variação do formato de frame FT3 da IEC 870-5-1. Tanto os frames da camada de enlace de dados quanto os da camada de aplicação podem ser transmitidos com serviço de confirmação de recebimento.

2. Estrutura flexível: a camada de aplicação do DNP3 é baseada em objetos, com uma estrutura que permite diversos níveis de implementação, mantendo a interoperabilidade entre eles.

3. Múltiplas aplicações: o DNP3 pode ser utilizado de diversas maneiras, incluindo:

• Polled (verificação periódica cíclica).

• Polled, report-by-exception

• Modo quiescente (unsolicited report-by-exception)

• Um misto dos modos anteriores

Ele pode ser utilizado com diferentes camadas físicas e, como é um protocolo organizado em camadas, pode operar em rede local ou numa WAN.

4. Overhead minimizado: o protocolo foi projetado para funcionar em enlaces de dados com taxas tão baixas quanto 1200 bps, utilizando o menor overhead possível para a flexibilidade projetada.

O DNP3 segue o modelo “Enhanced Performance Architecture” (EPA), especificado pela International Electrotechnical Comission (IEC) [3]. O EPA é uma versão simplificada do modelo ISO OSI (International Standards Organization Open Systems Interconnection).

Enquanto o modelo OSI especifica sete camadas, o modelo EPA trabalha com três: Física, Enlace de dados e Aplicação, conforme mostrado na figura 3.

Figura 3: Comparação entre as camadas dos modelos de referência OSI e EPA

(6)

A camada de usuário tem interface apenas com a camada de aplicação, não sendo necessário ter conhecimento das camadas de nível inferior. No modelo EPA, a camada de aplicação faz uso dos serviços da camada de enlace de dados. A especificação da camada de enlace de dados do DNP3 é apresentada em [4]. Essencialmente, a especificação descreve o formato dos quadros (frames), os serviços, responsabilidades e procedimentos de transmissão da camada, além dos serviços a serem fornecidos pela camada física. O DNP3 é, essencialmente, independente do meio físico quando a camada física atende seus requisitos. A camada de enlace de dados do DNP3 é bastante semelhante à especificada nas normas IEC 870-5-1 (1990) e IEC 870-5-2 (1992). A principal diferença é que o DNP3 utiliza o formato de quadro FT3 para transmissões assíncronas ao invés de síncronas. Além disso, o DNP3 adapta o esquema de endereçamento do IEC 870-5, incluindo tanto o endereço da fonte quanto do destino no quadro. Isto permite a utilização de múltiplas estações master e comunicação peer-to- peer com o DNP3. O protocolo DNP3 adiciona à arquitetura EPA uma “pseudo-camada de transporte” para segmentar os dados vindos da camada de aplicação em múltiplos frames de menor tamanho, compatíveis com o esperado pela camada de enlace de dados. Para cada frame, ela inclui um byte que indica se este é o primeiro frame da mensagem, o último, ou ambos simultaneamente (para uma mensagem com um único frame). Este byte ainda inclui um número que é incrementado a cada quadro. Isto permite que a camada de transporte da recepção consiga montar os quadros na seqüência correta e detecte a falta de algum deles. Maiores detalhes são encontrados em [6].

A seguir apresentam-se as principais características das camadas de enlace de dados e de aplicação do protocolo DNP3.

3.1. CAMADA DE ENLACE DNP3

A camada de enlace tem duas funções principais. A primeira é fornecer informações de transferência ou LSDU ( unidade de serviço de enlace de dados) através do enlace físico, como descrito no padrão ISO/OSI. Os dados do usuário fornecidos por camadas de nível mais alto (LSDU) devem ser convertidos em um quadro (ou LPDU –Link Protocol Data Unit) e enviados para a camada física para que sejam transmitidos. Similarmente, LPDU’s recebidas pela camada de enlace de dados devem ser montadas em uma LSDU e passadas para as camadas mais altas. Esta camada realiza a sincronização dos quadros e o controle de enlace. A segunda função da camada de enlace é fornecer as indicações de outros eventos tais como o status do enlace.

Estações Mestres, e sub-mestres, estações escravos e dispositivos eletrônicos inteligentes (IEDs) passam mensagens através da camada de enlace entre estações primárias (transmissoras/originárias das mensagens) e secundárias (receptoras). Com este protocolo, as mestres, sub-mestres, escravas e IEDs podem funcionar tanto como originárias (primárias) quanto como receptoras (secundárias).

A camada de enlace dá suporte para sistemas que empregam, por exemplo, um esquema de “polling”, sendo projetados para funcionar interligados com fios ou sem fios, operando de forma assíncrona ou síncrona, com transmissão serial por meio de dispositivos tais como RS-232C, RS-485 e fibra-ótica. Adota sistemas totalmente balanceados de maneira a possibilitar, que qualquer estação (mestre ou escrava) possa agir tanto como uma estação primária (transmissora) quanto como secundária (receptora), permitindo com isso o envio espontâneo de informações de uma estação externa (outstation), IEDs ou sub- mestres para o mestre. Esse esquema pode ser implementado com um canal full-duplex, possibilitando que as estações possam agir como primária e secundária ao mesmo tempo.

(7)

Se o canal for half-duplex, a estação pode assumir esses dois papeis, porém em momentos diferentes.

Uma transação entre a estação mestre e outra externa tem de ser completada em ambas estações antes que qualquer outra possa ser iniciada em qualquer uma delas. Tanto no caso da configuração full-duplex quanto na half-duplex, é responsabilidade de cada dispositivo implementar esquemas compatíveis para evitar colisões.

O protocolo DNP3 implanta parcialmente o modelo ISO/OSI, especificando apenas as camadas física, de enlace e de aplicação. Se for necessário utilizar funções mais avançadas e/ou enviar/receber mensagens de tamanho maior do que aquele definido pelo documento IEC 870-5-1, a camada de enlace deve ser usada junto com uma pseudo camada de transporte que, embora não seja parte desta, implementa a montagem e desmontagem de mensagens, adequando-as ao tamanho padrão do quadro.

3.1.1 Formato dos Quadros e Procedimentos DNP3

Um quadro FT3 é definido por um bloco de cabeçalho de comprimento fixo seguido de blocos opcionais de dados. Cada bloco tem um CRC (esquema de detecção de erros) de 16 bits agregado a ele. O IEC especifica que o campo do cabeçalho consiste de 2 octetos (bytes) de inicialização, 1 octeto de comprimento, 1 octeto de controle, um endereço de destino e um último, opcional, de dados com comprimento fixo. Neste caso, o campo do usuário com comprimento fixo é definido como o endereço fonte.

A figura 4 mostra as partes que constituem um quadro DNP3. A primeira - bloco-0 - é o cabeçalho e a segunda – bloco-n - é a seção de dados.

Figura 4: Formato de quadro FT3.

3.1.2 Campos do Quadro do Cabeçalho do Enlace de Dados Esta seção descreve o bloco-0 (cabeçalho) (fig. 4) da camada de enlace de dados.

Start

Este campo, que realiza a inicialização do cabeçalho, tem comprimento de 2 octetos (bytes). No primeiro octeto deve ser escrito 05H (hexadecimal) e no segundo 64H.

Length

Este campo tem comprimento de 1 octeto e é usado para contar os USER DATA no cabeçalho e no corpo da mensagem. Esta contagem inclui os campos CONTROL, DESTINATION e SOURCE do cabeçalho. Os campos CRC não estão incluídos. O valor mínimo para LENGTH é 5, indicando que somente o HEADER está presente, e o máximo 255.

Destination

Este campo, com comprimento de 2 octetos, especifica o endereço da estação de destino das informações. Ele está escrito na forma “big-endian” com o primeiro byte contendo o byte menos significativo (LSB) do endereço e o segundo o mais significativo (MSB). O endereço FFFF possibilita que todas estações aceitem estes quadros. O número

(8)

de endereços disponíveis é de 65520 – tanto para o destinatário quanto para o originário da mensagem - e cada dispositivo deve possuir um endereço único. Desse total, três endereços são reservados para que a comunicação se faça com todos dispositivos e 13 para algum tipo especial de uso no futuro.

Source

Este campo, de comprimento de bytes, especifica o endereço da estação de onde se originam os quadros. Este endereço é escrito de maneira similar ao campo “Destination”, com o byte menos significativo vindo primeiro e o mais significativo em seguida.

Control

Este campo de tamanho 1 byte (1 octeto) contém os bits para configuração da direção e tipo do quadro e do controle do fluxo de informações, conforme figura 5.

Figura 5: Bits do campo de controle do DNP3

Define-se estação-A como a estação mestre e estação-B como uma outra estação qualquer não-mestre. Da mesma forma, estação primária é a fonte de onde se origina a mensagem e estação secundária é o destino da mensagem.

Cada um dos bits do campo controla um aspecto da transação:

bit-7 (DIR) – define o sentido do fluxo de informações. Se o valor é 1 (um), as informações fluem da estação-A para a estação-B. Se ele vale 0, o fluxo é o oposto.

bit-6 (PRM) – define de onde se origina a informação. Se o valor é 1, o quadro é originário da estação primária. Se ele vale 0 (zero) o quadro vem da estação, que como se sabe, pode estar respondendo a uma mensagem ou pode ser uma estação escrava enviando uma mensagem não solicitada.

bit-5 (FCB) – este bit, frame count bit, é usado para suprimir perdas e duplicações de quadros da mesma estação secundária. Ele depende do bit-4 (FCV). O bit muda de valor para cada operação SEND-CONFIRM que é iniciada pela mesma estação primária e dirigida a mesma estação secundária. Uma estação secundária não deve aceitar outra mensagem vinda da estação primária até que um comando de

“reset” (reinicialização) tenha sido recebido e uma mensagem de confirmação enviada.

bit-4 ( FCV ou DFC) – Frame count valid verifica se a contagem do quadro é valida. Se ele está em zero o bit-5 (FCB) deve ser ignorado. Caso contrário, indica para a estação secundária que o bit FCB deve ser confrontado com este mesmo bit do último quadro enviado com o bit FCV =1.

Por outro lado, o DFC - Data Flow Control – é usado para evitar o transbordamento do buffer em uma estação secundária.

bit-3-0 (Function-code) - É usado para indicar o tipo de quadro enviado. Os valores para estação primária diferem dos da estação secundária. As tabelas abaixo mostram os códigos implementados e os estados FCV para cada um desses casos.

(9)

Fig.6a – Tabela da “function code” para a estação primária (PRM=1).

Fig.6b – Tabela da “function code” para a estação secundária (PRM=0).

Como mostrado na figura 6, a “function code” oferece várias possibilidades para controle das transações do protocolo DNP3. Em que pese o fato de existirem 15 códigos diferentes para comunicação iniciada por cada uma das estações, vários não tem função alguma e, portanto, não são usados.

Os códigos que são definidos pelo protocolo são:

Reset

É enviado com o propósito de sincronizar as estações primárias e secundárias para uma subseqüente transação SEND-CONFIRM. Assim que recebe um comando de RESET, a estação secundária fica preparada para aceitar mensagens (primária) da estação primária.

Isto é, a estação primária envia esta mensagem quando se comunica pela primeira vez com a estação secundária, ou em caso de uma falha reconhecida (pela estação primária).

Além disso, este comando habilita apenas comunicação vinda da estação primária para a estação secundária.

A estação primária envia estas funções códigos e a estação secundária deve responder também utilizando os códigos apropriados enviando um ACK – acknowledgment – ou NACK- no acknowledgment.

(10)

Reset of User Process

Código deve ser usado para re-inicializar um enlace de usuário. Assim que receber este comando, a estação secundária deve mandar uma indicação para o usuário que, então, irá re-inicializar o seu estado interno.

Test

Possibilita que o estado de um enlace secundário seja testado para evitar perdas de informações ou o envio duplicado. De foma similar ao caso anterior, assim que a estação secundária receber este comando, ela verifica o bit FCB da mensagem primária, para confirmar se ele tem o valor esperado para a estação primária que enviou a mensagem.

User Data

Este código é usado para enviar dados confirmados para uma estação secundária. Antes do início da comunicação, a estação secundária deve ser propriamente inicializada através de um comando RESET. O quadro enviado conterá os dados do usuário provenientes do usuário do enlace primário que serão passados para o usuário de enlace secundário.

Unconfirmed User Data

Existem situações em que a estação primária envia dados para a estação secundária e não requer confirmação de recebimento. O quadro enviado conterá os dados do enlace primário que devem ser passados para o enlace secundário.

Request Link Status

Em alguns casos é necessário conhecer o estado (status) do enlace secundário para que seja efetuado o envio de dados.

3.1.3. User Data

Os dados do usuário são enviados através de quadros que são compostos por conjuntos de blocos de 16 octetos (bytes) de dados definidos pelo usuário, com exceção do último bloco que pode ser menor para acomodar o volume restante, que pode conter um volume de dados de até 250 bytes.

A camada de enlace passa os dados do usuário e o endereço da estação de origem (quem envia) para as camadas mais altas quando recebe um quadro SEND de usuário.

3.2. A camada de Aplicação do DNP3

A camada de aplicação do protocolo é baseada no IEC 870-5-3 e IEC 870-5-4 [4].

Estruturalmente, o PDU (Protocol Data Unit) da camada de aplicação se enquadra na descrição do IEC para um APDU (Application Layer Protocol Data Unit). A camada constrói as mensagens que são passadas para a pseudo-camada de transporte, onde elas são segmentadas e repassadas para a camada de enlace de dados, que por sua vez as transmite usando os serviços da camada física.

Quando o volume de dados a ser transmitido em uma única mensagem (APDUs) é maior do que um certo valor limite estabelecido pelo tamanho da memória do dispositivo receptor (destino), os dados serão distribuídos entre várias mensagens menores, denominadas fragmentos, que irão ser transmitidos seqüencialmente. Para a camada de

(11)

aplicação, cada um desses fragmentos é como uma mensagem independente; sua associação com as demais é uma indicação contida na própria mensagem - com exceção da última - que outras vão vir em seqüência. Mensagens multi-fragmentadas vindas de uma estação DNP3 Master são geradas tipicamente por requisições para operações em vários objetos de dados. Fragmentos vindos de estações Slave são tipicamente gerados a partir de respostas a estas requisições. Os fragmentos são também conhecidos por ASDU (Application Service Data Unit). Portanto, no DNP3, um APDU pode ser convertido em múltiplos ASDUs.

Os fragmentos da camada de aplicação (ASDUs) podem ser enviados com uma requisição de confirmação. Uma confirmação da camada de aplicação indica que uma mensagem, não somente foi recebida, mas também foi interpretada sem erros (por outro lado, uma confirmação da camada de enlace de dados, somente indica que o frame do enlace de dados foi recebido e que a verificação do CRC foi efetuada sem erros).

Um Slave DNP3 também pode transmitir uma mensagem sem que haja uma requisição do Master, constitui uma resposta não solicitada.

Cada ASDU é prefixado por um cabeçalho, seguido por uma ou mais combinações de objetos ou cabeçalho/objeto. O cabeçalho da camada de aplicação contém um campo de controle e um código de função. O campo de controle contém:

• uma indicação se o fragmento é parte de uma mensagem com múltiplos fragmentos;

• indicação se uma confirmação da camada de aplicação é necessária para o fragmento;

• uma indicação se o fragmento foi não solicitado;

• um número de seqüência do fragmento.

O número de seqüência do fragmento permite que a camada de aplicação do receptor do fragmento identifique fragmentos fora da seqüência, ou fragmentos perdidos. A figura 7 mostra a estrutura do APDU do DNP3. Maiores detalhes sobre a definição dos diversos campos da mensagem são encontrados em [4].

(12)

Figura 7: Estrutura do APDU do DNP3

O código de função do cabeçalho do ASDU indica o propósito, ou operação solicitada pela mensagem. Apesar do DNP3 permitir múltiplos tipos de dados em uma única mensagem, ele permite apenas um tipo de operação por mensagem. As funções incluem [4]:

• Confirm: para confirmações na camada de aplicação;

• Read: requisição de leitura;

• Write: requisição de escrita;

• Select and Operate (para funções do tipo “Select Before Operate”, SBO);

• Direct Operate (sem SBO);

• Freeze: copia os objetos especificados para um “freeze buffer”;

• Freeze and Clear: copia os objetos especificados para um “freeze buffer” e então os limpa;

• Restart (cold and warm);

• Initialize Data to default;

• Initialize, Start and Stop Application;

(13)

• Save Configuration;

• Enable e Disable de mensagens não solicitadas;

• Assign Classes;

• Delay Measurement.

A figura 8 mostra a classe CDNP3, conforme implementada no conversor de protocolos, indicando as funções anteriores, além de outras da camada de aplicação do DNP3 [3].

Figura 8: Classe CDNP3 do conversor de protocolos

O modelo de dados do protocolo DNP3 permite uma ampla gama de variações de tipos de dados. O termo estático aplicado sobre dados se refere ao valor atual do dado. Então, um dado de entrada estático binário se refere ao valor atual (on/off) de um dispositivo de dois estados. Valores de entrada analógicos estáticos contêm os valores da entrada analógica no instante em que ela foi transmitida. O DNP3 permite que se solicite parte ou todos os dados estáticos presentes em um dispositivo escravo.

Os eventos no DNP3 estão associados a um acontecimento significativo. Exemplos são mudanças de estado, valores excedendo determinados limites, dados de transitórios e informação nova disponível. O DNP3 fornece também a possibilidade de reportar eventos com ou sem “time stamps”, (referência do tempo de ocorrência do evento). A camada de usuário pode direcionar o DNP3 a solicitar eventos. Geralmente, um cliente é atualizado mais rapidamente se ele solicita apenas eventos do servidor e somente ocasionalmente solicita dados estáticos, como forma de garantir a integridade dos dados.

CDNP3 CDNP3()

~CDNP3()

request_data_link_service() Confirmation()

Read() Mount_ADU() Write() Test() ResetUser() ResetLink() Select()

DelayMeasurement() AssignClasses()

DisableSpontaneousMsgs() EnableSpontaneousMsgs() SaveConfiguration() StopApplication() StartApplication() InitializeData() WarmRestart() ColdRestart() FreezeWithTime() FreezeAndClearNoAck() FreezeAndClear() ImmediateFreezeNoAck() ImmediateFreeze() DirectOperateNoAck() DirectOperate() Operate() LinkStatus()

InsertQualifierAndData() Mount_ADU_Response() SendACK()

Response()

request_blocking_data_link_service()

(14)

A razão pela qual a solicitação de eventos é mais rápida é o fato de que o número de eventos gerado entre duas solicitações ao servidor é geralmente pequeno e, consequentemente, menos dados precisam ser retornados ao cliente. O DNP3 ainda avança mais um passo, classificando os eventos em três classes: quando o protocolo foi concebido, os eventos de classe 1 eram considerados como tendo maior prioridade que os eventos de classe 2 e estes tinham maior prioridade que os eventos de classe 3.

Apesar deste esquema ainda poder ser configurado, alguns usuários DNP3 desenvolveram outras estratégias: por exemplo, a camada de usuário pode solicitar à camada de aplicação buscar os eventos de classe 1, 2 ou 3, ou qualquer combinação deles.

O DNP3 possibilita representar dados em diferentes formatos. É interessante analisar o formato dos dados analógicos para entender a flexibilidade do DNP3. Valores analógicos correntes (estáticos) podem ser representados por variações, como se segue:

1. Um inteiro de 32 bits, com flag, 2. Um inteiro de 16 bits, com flag, 3. Um inteiro de 32 bits,

4. Um inteiro de 16 bits,

5. Um número em ponto flutuante de 32 bits, com flag e 6. Um número em ponto flutuante de 64 bits, com flag.

O flag das grandezas acima é um octeto (byte) com os seus bits indicando se a fonte de dados está on-line, se o valor contém um valor de restart, se a comunicação com a fonte de dados está perdida, se o dado é forçado ou se o valor está fora de limite. Nem todos os dispositivos DNP3 podem transmitir ou interpretar todas as 6 variações. De fato, isto depende do nível da implementação do protocolo. Porém, todos os dispositivos DNP3 devem ser capazes de transmitir as variações mais simples.

Valores analógicos de evento podem ser representados pelas seguintes variações:

1. Um inteiro de 32 bits com flag, 2. Um inteiro de 16 bits, com flag,

3. Um inteiro de 32 bits com flag e tempo de evento, 4. Um inteiro de 16 bits, com flag e tempo de evento, 5. Um número em ponto flutuante de 32 bits, com flag, 6. Um número em ponto flutuante de 64 bits, com flag,

7. Um número em ponto flutuante de 32 bits, com flag e tempo de evento e 8. Um número em ponto flutuante de 64 bits, com flag e tempo de evento.

O flag tem os mesmos campos de bit das variações estáticas.

Aparentemente, as variações 1 e 2 dos eventos analógicos não podem ser diferenciadas das variações 1 e 2 dos valores estáticos analógicos. A diferenciação é feita no protocolo DNP3 associando-se números (tipos) aos objetos de dados. Valores estáticos analógicos recebem o número de objeto 30 e valores de eventos analógicos recebem o número de objeto 32. Valores estáticos analógicos (objeto 30) podem ser formatados em uma de 6 possíveis variações e valores de evento analógico (objeto 32) podem ser formatados em uma de 8 possíveis variações. Quando um servidor DNP3 transmite uma mensagem contendo os dados de resposta, a mensagem identifica o número do objeto e a variação de cada objeto de dados na mensagem.

(15)

Números de objeto e variações também são atribuídos a contadores, entradas digitais, controles e saídas analógicas. Todos os tipos de dados válidos do DNP3 são identificados por um número de objeto e variação. A referência [5] descreve cada um dos tipos e suas variações e a figura 9 apresenta a hierarquia de classes utilizada no conversor de protocolos para implementar os objetos DNP. Cada um dos objetos deve ser capaz de interpretar as várias variações existentes, além de efetuar a extração e formatação dos dados do objeto de/para as mensagens DNP.

Figura 9: Hierarquia dos objetos DNP, que implementa os diversos objetos e variações do DNP3

A camada de usuário do cliente do protocolo efetua uma requisição de dados do servidor dizendo para a camada de aplicação qual a função a ser executada (por exemplo, efetuar uma leitura) e especificando quais objetos ela deseja do servidor. A requisição pode especificar quantos objetos deseja, ou escolher alguns objetos específicos a serem lidos, ou uma faixa de objetos entre determinados índices. A camada de aplicação passa a requisição para a pseudo-camada de transporte, que a passa para a camada de enlace de dados que, por sua vez, envia a requisição para o servidor. A camada de enlace de dados do servidor recebe os quadros e verifica se ocorreram erros. Caso estejam corretos, passa-os para a camada de transporte, onde a mensagem completa é montada para a camada de aplicação do servidor.

As respostas do servidor funcionam de forma similar. A camada de usuário busca os dados solicitados e os apresenta para a camada de aplicação, que formata os dados em objetos e variações. Os dados são, então, passados para as camadas inferiores no lado do servidor, transmitidos, recebidos e transferidos para as camadas superiores no lado do cliente. Aqui, os objetos de dados são recuperados na camada de usuário em uma forma que é nativa ao banco de dados do cliente, utilizando os serviços dos objetos DNP mostrados na figura 9.

CBinary Output

CDNPObject

<<v irtual>> ~CDNPObject()

<<v irtual>> FormatResponse()

<<static>> Range2IndexSize()

<<v irtual>> FormatDataObject()

<<v irtual>> GetRangeMaster()

<<v irtual>> GetRangeSlav e()

<<abstract>> GetData()

<<abstract>> GetOneData() CalcHasCRC()

CFrozenAnalogInput CAnalogInput

CAnalogOutputBlock

CAnalogOutputStatus

CApplicationId

CBinary Counter

CBinary Input

CBinary InputChange

CClassData CControlRelay OutputBlock

CCounterChangeEv ent CDateAndTime

CFileId

CFrozenCounter CFrozenCountEv ent CInternalIndications CPriv ateRegistration

CBinary

CTimeDelay

(16)

Além das funcionalidades de leitura, o protocolo DNP3 oferece outras funcionalidades para os clientes. Por exemplo, o cliente pode escolher o valor do tempo no servidor. O cliente pode transmitir requisições para “congelar” acumuladores, requisições para operações de controle e para configurar saídas analógicas utilizando uma seqüência

“select before operate (SBO)” ou uma operação direta.

Um ponto importante se refere aos níveis de implementação do protocolo DNP3. Não é necessário que todos os tipos de dispositivos dêem suporte a todas as características do protocolo. Alguns dispositivos possuem memória limitada, têm velocidade de comunicação reduzida, ou não necessitam de algumas funcionalidades específicas, enquanto outros necessitam de funcionalidades mais avançadas para desempenhar suas tarefas. Assim, o DNP3 é organizado em 3 níveis de complexidade: no nível mais básico, nível 1, apenas algumas poucas funcionalidades básicas são implementadas e as demais são opcionais. O nível 2 trabalha com mais funções, objetos e variações e o nível 3 é o mais completo. Em cada nível, apenas algumas combinações de formatos de requisição e de resposta são necessárias. O protocolo foi assim organizado para limitar a complexidade do software necessário para clientes e servidores e, ainda assim, garantir a interoperabilidade dos sistemas.

(17)

4. O conversor de protocolos.

A arquitetura do conversor de protocolos está organizada em três camadas: uma camada de acesso ao Banco de dados, uma camada de Controle e uma camada de acesso aos Protocolos, conforme indicado na figura 10:

Figura 10: Arquitetura em Camadas do Servidor de Protocolos

Inicialmente não havia comunicação direta entre a camada do Banco de dados e a de Protocolos. Porém, como será visto posteriormente, a partir da introdução de um protocolo para acesso ao banco de dados, a camada de protocolos passou a fazer uso dos serviços da camada de Banco de Dados.

A seguir, será feita uma introdução a cada uma das camadas, o que permitirá um entendimento de alto nível do sistema implementado. Maiores detalhes podem ser obtidos no arquivo de projeto que acompanha este relatório [8]

4.1. A camada do Banco de dados

O núcleo do conversor de protocolos é uma base de dados SQL encapsulada pela camada de Banco de dados. Na base de dados estão armazenados os dados de configuração, valores lidos nas entradas (analógicas e digitais) dos dispositivos, valores a serem atribuídos às saídas (analógicas e digitais) e os eventos e alarmes ocorridos no sistema. A descrição completa da base de dados (tabelas e campos utilizados) é apresentada em outro documento [11].

Na camada de banco de dados foi criada uma classe, DBProxy, cujo papel é intermediar as requisições SQL. Qualquer tentativa de leitura ou escrita na base de dados deve ser feita por DBProxy, que encapsula o conhecimento sobre como as tabelas estão organizadas e como acessa-las.

As classes que implementam a camada de Banco de dados estão mostradas na figura 11.

Nesta figura, além de DBProxy, são também mostradas as classes que permitem que DBProxy funcione como um Observador [18] da base de dados. Quando se necessita da modificação de uma das saídas do sistema, o registro correspondente à saída na base de dados é modificado externamente ao conversor (por exemplo, pela IHM). A classe DBChange, que funciona como um tipo de Subject [18], se encarrega de monitorar a base de dados, notificando os seus Observadores (no caso um objeto da classe DBProxy) que a modificação externa ocorreu. DBProxy, então, deve buscar as informações correspondentes à mudança na tabela de saída e enviar uma requisição à classe de Controle, que se incumbirá de acionar o Protocolo de comunicação correspondente ao

Banco de Dados

Controle

Protocolos

(18)

dispositivo associado à saída modificada. Na figura 11 também pode ser notado que toda interface da camada de Banco de dados com a camada de Controle é feita através da interação entre DBProxy e ControlInitiate, que estão funcionando como Facades [18]

destas camadas.

Figura 11: Classes que implementam a camada de Banco de dados e sua comunicação com a camada de Controle.

Deve-se notar que existe comunicação entre a camada de Banco de Dados e a camada de Protocolos, através do protocolo de acesso ao banco de dados (DB), mas isto será detalhado quando da apresentação da camada de protocolos, no item 4.3. A figura 12 apresenta os serviços fornecidos pela classe DBProxy. Note-se a presença de métodos para conexão ao banco de dados, leitura e escrita de dados analógicos e digitais, leitura de configuração de dispositivos, etc.

Figura 12: Classe DBProxy

DBChange ControlInitiate

(from Controle)

DBProxy -m_subject

-m_proxy

-m_initializer Subject

m_Observers : list<Observer*> Observer

Camada de Banco de dados Camada de Controle

DBProxy DBProxy()

WriteAnalogInputValues() WriteDigitalInputValues() Update()

WriteDigitalOutputValue() ReadDispositivoT able() SetSD()

GetT abelaED() GetT abelaEA() GetSDvalues() GetDevices() WriteTime() GetInfo() GetAllDevices()

ReadDigitalInputValues() ReadAnalogInputValues()

<<virtual>> ~DBProxy() ReadDigitalOutputValues() ReadAnalogOutputValues() WriteAnalogOutputValues() WriteDigitalOutputValues() OperateDigitalOutputValues() OperateAnalogOutputValues() SelectAnalogOutput() SelectDigitalOutput() WriteAnalogOutputValue() SelectDigitalOutputValue() SelectAnalogOutput() OperateAnalogOutputValue() ConstroiVenderecos()

(19)

4.2. A camada de Controle

A camada de Controle contém as classes responsáveis por efetuar a interface entre a camada de Bancos de dados e os diversos protocolos encapsulados na camada de Protocolos. Ela oferece uma interface homogênea para acesso ao banco de dados, seja qual for o protocolo que estiver atuando em um determinado instante de tempo. Da mesma maneira, a camada de Banco de dados enxerga uma interface constante, seja qual for o protocolo de comunicação a ser utilizado (exceto o protocolo de acesso ao banco de dados, como veremos no item 4.3).

A camada de Controle é implementada pela classe ControlInitiate, que se comunica com a camada de Banco de dados através da classe DBProxy e com a camada de Protocolos através da classe abstrata Protocol (figura 13).

Figura 13: A camada de Controle e sua relação com as camadas de Banco de dados e de Protocolos

A classe ControlInitiate é responsável por:

• Instanciar a classe DBProxy: esta, por sua vez, quando instanciada, instancia os demais objetos da camada do Banco de dados, criando o serviço de observação do banco de dados (item 4.1);

• Solicitar a DBProxy os dados de configuração do sistema. A partir destes dados a classe é capaz de instanciar os objetos de protocolo (mestres e escravos) e inicializa-los corretamente;

• Intermediar a comunicação entre a camada de Banco de dados e a camada de Protocolos.

• Efetuar o polling de leitura das entradas dos dispositivos. Este serviço é implementado em uma thread específica, disparada de acordo com intervalos de tempo estipulados na configuração do sistema.

• Efetuar a sincronização dos relógios dos dispositivos Este serviço também é implementado por thread específica, disparada de acordo com intervalos de tempo estipulados na configuração do sistema.

A figura 14 apresenta os serviços fornecidos pela classe ControlInitiate. Note-se a presença de funções para configurar o sistema a partir do banco de dados (ConfigSystem), habilitar e desabilitar os serviços de polling, enviar requisições específicas para os protocolos (Send...), etc.

Camada de Banco de dados Camada de Controle Camada de Protocolos

DBProxy (from Banco de Dad...

Protocol (from Protocol...

ControlInitiate

-m_proxy -m_initializer -m_protocol

(20)

Figura 14: Classe ControlInitiate

4.3. A camada de Protocolos

A camada de Protocolos encapsula os protocolos de comunicação utilizados pelo sistema, figura 15.

Figura 15: Hierarquia dos Protocolos.

ControlInitiate ControlInitiate()

~ControlInitiate() InsertDevice()

SendDigitalOutputMessage() ConfigSystem()

GetActiveProtocol() DesabilitaPolling() HabilitaPolling() GetProxy()

SendAnalogOutputMessage() SendSelectDigitalMessage() SendSelectAnalogMessage() SendInhibitSelectMessage() SendOperateAnalogMessage() SendOperateDigitalMessage() SendSynchronizeMessage() SendResetMessage() SendGetIEDTimeMessage() SendGetInfoIEDMessage() SendInterrogaMessage() GetDeviceData()

Protocol

Protocol()

<<v irtual>> ~Protocol()

<<abstract>> DigitalOutputWrite()

<<abstract>> InsertNewMaster()

<<abstract>> DigitalInputRead()

<<abstract>> AnalogInputRead()

<<abstract>> AnalogOutputWrite()

<<abstract>> SelectDigital()

<<abstract>> SelectAnalog()

<<abstract>> InhibitSelect()

<<abstract>> OperateDigital()

<<abstract>> OperateAnalog()

<<abstract>> Sy nchronize()

<<abstract>> GetIEDTime()

<<abstract>> Diagnostics()

<<abstract>> Inf ormation()

<<abstract>> Reset()

<<abstract>> Interroga()

CRP570 (from RP570)

CModbusServ er (from Modbus) +instancePtr

CDNP3Serv er (from DNP3)

+instancePtr -$instancePtr

CDNP3 (from DNP3)

CModbus (from Modbus)

CRP570Serv er (from RP570) +instancePtr

-$instancePtr

CDBServ er (from DB)

+instancePtr

-$instancePtr

(21)

Os tipos de protocolos instanciados dependem da configuração armazenada na base de dados. No momento, os protocolos totalmente implementados são o DNP3, Modbus, DataBase (DB) e tem-se também a implementação parcial do protocolo RP570. Outros protocolos podem ser facilmente adicionados a partir da herança da classe abstrata Protocol, que define a interface de todos os protocolos (figura 15). Nota-se que cada protocolo implementa uma classe concreta que atua como um servidor para aquele protocolo (CDNP3Server, CmodbusServer, CRP570Server e CDBServer). Este servidor pode gerenciar uma série de dispositivos (escravos ou mestres) a ele conectados.

Todos os métodos de Protocol são virtuais puros (<<abstracts>>) e, portanto, devem ser implementados nos protocolos concretos derivados desta classe. Utilizando esta estratégia, todos os tipos de protocolo podem ser manipulados por uma única interface genérica (a definida por Protocol), apesar de cada um implementar suas funcionalidades de maneira específica. As funcionalidades atualmente presentes na interface de Protocol foram definidas a partir de discussões entre as equipes da UFMG e CEMIG e são elas que definem o processo de conversão entre os diversos protocolos. Caso haja necessidade de alguma nova funcionalidade para a conversão de protocolos, basta adiciona-la à interface de Protocol e implementa-la nas classes derivadas, utilizando os serviços dos protocolos específicos. Isto foi feito totalmente para os protocolos Modbus e DNP3, e, parcialmente, para o protocolo RP570, usando os serviços apresentados na tabela 3.

Tabela 3: Relação entre as funcionalidades presentes na interface da classe abstrata Protocol e sua implementação pelos protocolos concretos

Função Função no Conversor Modbus DNP3 RP570

1Ler Entrada Digital DIGITAL DigitalInputRead(...); Read Coils Read RX/IDM/IDS 2Ler Entrada

Analógica

ANALOG AnalogInputRead(...); Read Input Register Read RX/AVM/AVS 3Escrever Saída

Digital void DigitalOutputWrite(...) ; Write Single Coil/Write Multiple

Coils1

Write1/Direct

Operate RX/GOM/SPM

4Escrever Saída

Analógica void AnalogOutputWrite(...) ; Write Single Register/Write Multiple Registers1

Write1/Direct

Operate RX/GOM/SPM

5Comando de 2

passos (SBO) int SelectAnalog(...);

int SelectDigital(...);

int InhibitSelect(...);

int OperateAnalog(...);

int OperateDigital(...);

feito no conversor feito no conversor feito no conversor AnalogOutputWrite

DigitalOutputWrite

Select Select por timeout

Operate Operate

CBXC/EXC/IHC

6Sincronização2 int Synchronize(...); ? Write Date&Time TSI

7Timestamp IED3 TIMESTAMP GetIEDTime(...); feito no conversor Read Date&Time ERMI

8Diagnóstico IED4 DIAGNOSTICO Diagnostics(...); Diagnostics ? ?

9Informações IED INFO Information(...); Read Device Identification/ Read

Slave ID

Read Private Registration Object

TSTA

10Reset IED5 int Reset(...); Diagnostics? Cold Restart/Warm FCOM

11Requisição de Dados6

Interroga(...); ReadCoils/ReadInpu tRegister

Read RB

Observações:

1- A segunda opção de comandos foi escolhida para executar a sua respectiva função genérica 2- Para o Modbus esta função retorna sempre falso pois não é possível a sincronização com este

protocolo

3- No Modbus, o relógio é simulado no conversor 4- Diagnóstico não está definido para DNP e RP570

5- No Modbus só é possível reconfigurar comunicação e não IED

6- A atualização periódica também é realizada pela função 11, Requisição de dados.

(22)

4.3.1. Protocolo Modbus.

A classe Cmodbus implementa as funcionalidades do protocolo Modbus e a CmodbusServer, dela derivada, implementa as funcionalidades definidas pela classe abstrata Protocol (figura 16). Cada CModbusServer possui um ou mais objetos do tipo CModbusSlave, que encapsulam os dispositivos escravos conectados ao servidor.

Figura 16: Implementação do protocolo Modbus RTU

Como as funcionalidades de comunicação com os escravos dependem do sistema operacional, a classe CModbusSlave é especializada nas classes WModbusSlave (Windows) e LModbusSlave (Linux). No momento, apenas a classe WModbusSlave se

Protocol (from Protocolos)

CModbus CModbus()

<<virtual>> ~CModbus()

<<abstract>> TxRcMessage()

<<abstract>> Mount_ADU() ReadDiscreteInputs() ReadCoils() WriteSingleCoil() WriteMultipleCoils() ReadInputRegister() ReadHoldingRegister() WriteSingleRegister() WriteMultipleRegisters() Calc_CRC()

Calc_Resp_CRC() MaskWriteRegister() ReadFIFOQueue() ReadFileRecord() WriteFileRecord() ReadExceptionStatus() Diagnostic()

GetCOMEventCounter() GetCOMEventLog() ReportSlaveID() ReadDeviceID()

CModbusSlave CModbusSlave()

<<virtual>> ~CModbusSlave()

<<abstract>> WriteCom()

CModbusServer CModbusServer()

<<static>> Instance()

<<virtual>> ~CModbusServer() SetSlaveAddress()

<<virtual>> TxRcMessage()

<<virtual>> InsertNewMaster()

<<virtual>> DigitalOutputWrite() Mount_ADU()

<<virtual>> DigitalInputRead()

<<virtual>> AnalogInputRead()

<<virtual>> AnalogOutputWrite()

<<virtual>> SelectDigital()

<<virtual>> SelectAnalog()

<<virtual>> InhibitSelect()

<<virtual>> OperateDigital()

<<virtual>> OperateAnalog()

<<virtual>> Synchronize()

<<virtual>> GetIEDTime()

<<virtual>> Diagnostics()

<<virtual>> Information()

<<virtual>> Reset()

<<virtual>> Interroga() CheckException()

+instancePtr

-$instancePtr

TabEscravo (f rom CModbusServ er) -m_tabSlave

LModbusSlave WModbusSlave

WModbusSlave()

<<virtual>> ~WModbusSlave() WriteCom()

WaitForResponse()

PCRS232 (f rom Protocolos) -m_Cserial

(23)

encontra implementada. Na implementação desta classe é utilizado um objeto da classe PCRS232 que permite o acesso à porta serial (Figura 16).

4.3.2. Protocolo DNP3.

A implementação do protocolo DNP3 utiliza as classes apresentadas na figura 17.

Figura 17: Implementação do protocolo DNP3

A classe CDNP3, já apresentada anteriormente na figura 8, implementa as funcionalidades da camada de aplicação do protocolo DNP3. Por outro lado, CDNP3Server implementa a interface genérica definida para a classe Protocol usando os serviços herdados de CDNP3.

Cada CDNP3Server possui um ou mais dispositivos DNP3 a ele conectados e esta conexão é realizada através da classe CDNP3Device, que pode ser especializada em WDNP3Slave (o protocolo funcionando como escravo DNP3) ou WDNP3Master (o protocolo funcionando

WDNP3Master m_hMutex : HANDLE WDNP3Master()

~WDNP3Master() WriteCom()

request_blocking_data_link_service() ThreadDNPReceiveDataLink() ProcessaMsg()

WaitForResponse()

Mount_And_Send_Blocking_TPDU() Mount_And_Send_Blocking_LPDU() Transmit_Blocking_Message() Protocol

(from Protocolos)

CDNP3 CDNP3()

~CDNP3()

request_data_link_service() Confirmation()

Read() Mount_ADU() Write() Test() ResetUser() ResetLink() Select()

DelayMeasurement() AssignClasses() DisableSpontaneousMsgs() EnableSpontaneousMsgs() SaveConfiguration() StopApplication() StartApplication() InitializeData() WarmRestart() ColdRestart() FreezeWithTime() FreezeAndClearNoAck() FreezeAndClear() ImmediateFreezeNoAck() ImmediateFreeze() DirectOperateNoAck() DirectOperate() Operate() LinkStatus()

InsertQualifierAndData() Mount_ADU_Response() SendACK()

Response()

request_blocking_data_link_service()

CDNP3Device CDNP3Device()

<<virtual>> ~CDNP3Device()

<<abstract>> WriteCom() Calc_Resp_CRC() Insert_CRC() Calc_CRC()

Mount_And_Send_TPDU() Mount_And_Send_LPDU() Transmit_Message()

<<virtual>> request_data_link_service()

CSerialEx

(from Protocolos)

WDNP3Slave m_hMutex : HANDLE

m_hThreadDNPSlave : HANDLE WDNP3Slave()

<<virtual>> ~WDNP3Slave() WriteCom()

<<static>> ThreadDNPReceiver() ThreadDNPReceiver()

ProcessaMsgSlave() DispatchDataToDestination()

<<virtual>> request_data_link_indications() StartThread()

StopThread()

-m_Cserial

PCRS232

(from Protocolos)-m_Cserial TabEscravo

(from CDNP3Server)

<<typedef>>

TabMestre

(from CDNP3Server)

<<typedef>>

CDNP3Server CDNP3Server()

<<static>> Instance()

<<virtual>> ~CDNP3Server()

<<virtual>> InsertNewMaster()

<<virtual>> DigitalOutputWrite()

<<virtual>> DigitalInputRead()

<<virtual>> AnalogInputRead() request_data_link_service()

<<virtual>> AnalogOutputWrite()

<<virtual>> SelectDigital()

<<virtual>> SelectAnalog()

<<virtual>> InhibitSelect()

<<virtual>> OperateDigital()

<<virtual>> OperateAnalog()

<<virtual>> Synchronize()

<<virtual>> GetIEDTime()

<<virtual>> Diagnostics()

<<virtual>> Information()

<<virtual>> Reset()

<<virtual>> Interroga() SendConfirmation()

request_blocking_data_link_service() InsertNewSlave()

+instancePtr -m_tabSlave

-m_tabMaster

(24)

como mestre DNP3) ambos para o sistema operacional Windows. WDNP3Master faz uso dos serviços de PCRS232 para efetuar a comunicação serial e WDNP3Slave faz uso dos serviços de CSerialEx, derivada de PCRS232. O uso de CSerialEx se impõe para WDNP3Slave, pois esta classe deve tratar requisições vindas de dispositivos mestre DNP e foi necessário extender os serviços oferecidos pela classe PCRS232 para isto.

A classe CDNP3Server, portanto, gerencia todos os mestres e escravos DNP3 conectados ao conversor de protocolos. O tratamento das requisições feitas pelos mestres DNP3 segue uma hierarquia de threads, assim organizada:

1. A classe CSerialEx executa a thread CSerialEx::ThreadProc, que espera por eventos da porta serial à qual está associada. No caso de recebimento de dados, ela verifica se os dados são correspondentes a uma mensagem DNP3 (verificando o seu cabeçalho), coloca estes dados na fila de mensagens DNP3 e sinaliza que os dados estão disponíveis para a próxima thread na hierarquia, a CDNP3Server:: ThreadDNPReceiveDataLink; 2. A thread WDNP3Slave::ThreadDNPReceiver executa a função

WDNP3Slave::request_data_link_indications que espera pela sinalização de que uma mensagem está disponível, retira esta mensagem da fila DNP3, verifica a integridade da mesma (testa cabeçalhos e CRC), extrai seu conteúdo (usando os objetos DNP3 da hierarquia de objetos apresentada na figura 9), e envia o resultado decodificado para a função WDNP3Slave::ProcessaMsgSlave .

3. WDNP3Slave::ProcessaMsgSlave executa a requisição, retornando a resposta para o dispositivo que a efetuou.

4.3.3. O protocolo DataBase (DB)

O protocolo DB foi criado de maneira a facilitar o acesso ao banco de dados via conversor de protocolos. A idéia básica foi a de criar um protocolo que seguisse a interface definida pela classe Protocol e que atendesse as requisições registrando-as no banco de dados do conversor. Desta maneira, o registro dos valores de entradas/saídas no banco de dados ficou muito mais simples, pois passou a ser feita através da mesma interface dos demais protocolos. Ou seja, para escrever uma saída digital no banco de dados basta buscar o dispositivo associado ao protocolo DB e chamar o método DigitalOutputWrite sobre ele.

A implementação do protocolo DB utiliza as classes apresentadas na figura 18. Note-se que para que o protocolo possa ler e armazenar dados no banco de dados, é necessário o acesso a ele, o que é feito através de um objeto DBProxy. Desta maneira, a existência deste protocolo trouxe o acoplamento entre a camada de protocolos e a de banco de dados, apesar deste acoplamento ser bastante fraco, só existente via protocolo DB. Além disto, além dos métodos previstos na interface da classe Protocol, verifica-se que foram adicionados mais 4 métodos: AnalogInputWrite, AnalogOutputRead, DigitalInputWrite e DigitalOutputRead, de maneira que todos os dados armazenados no banco de dados sejam acessíveis pelo protocolo.

(25)

Figura 18: Implementação do protocolo DB

Todas as funções da interface genérica recebem como parâmetros o dispositivo fonte (o dispositivo que gerou a requisição, e para o qual a resposta deve ser enviada) e o dispositivo destino (o dispositivo para o qual a requisição é enviada e que responde a ela). Uma convenção importante com relação à escolha de fonte e destino para o protocolo DB deve ser ressaltada: como neste protocolo se quer acessar as informações de todos os dispositivos presentes no banco de dados, utiliza-se a informação sobre o dispositivo fonte para escolher qual dispositivo do banco de dados se vai acessar. Neste caso, o dispositivo destino será sempre o associado ao banco de dados. Assim, se tivermos um dispositivo DNP3 com endereço 3 e um dispositivo DB com endereço 4 e quisermos ler a tabela de entradas digitais do dispositivo DNP3, armazenada no banco de dados, faremos uma requisição DigitalInputRead, usando o protocolo DB, em que o dispositivo fonte será o 3 e o dispositivo destino será o 4.

Para os demais protocolos usa-se um endereçamento normal de fonte e destino: fonte é o dispositivo que gerou a requisição e para o qual a resposta deve ser enviada e destino é o dispositivo para o qual a requisição é enviada e que responde a ela.

Camada de Banco de dados Camada de Protocolos

Protocol

Protocol()

<<virtual>> ~Protocol()

<<abstract>> DigitalOutputWrite()

<<abstract>> InsertNewMaster()

<<abstract>> DigitalInputRead()

<<abstract>> AnalogInputRead()

<<abstract>> AnalogOutputWrite()

<<abstract>> SelectDigital()

<<abstract>> SelectAnalog()

<<abstract>> InhibitSelect()

<<abstract>> OperateDigital()

<<abstract>> OperateAnalog()

<<abstract>> Synchronize()

<<abstract>> GetIEDTime()

<<abstract>> Diagnostics()

<<abstract>> Information()

<<abstract>> Reset()

<<abstract>> Interroga()

(from Protocolos) CDBServer

CDBServer()

<<static>> Instance()

<<virtual>> ~CDBServer() InsertNewMaster()

<<virtual>> DigitalInputRead()

<<virtual>> AnalogInputRead()

<<virtual>> DigitalOutputWrite()

<<virtual>> AnalogOutputWrite()

<<virtual>> SelectDigital()

<<virtual>> SelectAnalog()

<<virtual>> InhibitSelect()

<<virtual>> OperateDigital()

<<virtual>> OperateAnalog()

<<virtual>> Synchronize()

<<virtual>> GetIEDTime()

<<virtual>> Diagnostics()

<<virtual>> Information()

<<virtual>> Reset()

<<virtual>> Interroga() AnalogInputWrite() AnalogOutputRead() DigitalInputWrite() DigitalOutputRead()

+instancePtr -$instancePtr

DBProxy (f rom Banco de Dad...) +m_ptDBProxy

(26)

5. Considerações de implementação

A implementação do sistema foi efetuada utilizando-se a linguagem C++ e, inicialmente, o compilador Microsoft Visual C++ 6.0. Posteriormente o sistema foi migrado para a plataforma Microsoft Visual C++ .NET, versão 7.1 (2003). Duas versões do conversor de protocolos foram criadas. A primeira trabalha em modo console e não existe qualquer tipo de interação com o usuário. Ela apenas envia para a tela algumas informações sobre como o conversor de protocolos está funcionando. A segunda versão abre uma janela Windows e através dela é possível monitorar a execução do conversor de protocolos como mestre ou como slave. Além disto, pode-se testar a funcionalidade de cada protocolo individualmente, seja através das funções genéricas da interface definidas pela classe base Protocol, seja através das funções específicas definidas para cada protocolo em sua especificação. O acesso a estas funcionalidades é efetuado utilizando uma interface padrão Windows.

Os arquivos fonte e os executáveis correspondentes estão sendo entregues em CD-ROM anexado a este relatório [9]. Para a versão console do sistema foram criadas 63 classes e um programa principal. Para a versão Windows, que foi baseada na biblioteca de classes MFC da Microsoft, além das 63 classes anteriores, são usadas mais 2 classes: a referente à janela principal do aplicativo (CConversorMFCDlg, uma caixa de diálogos) e outra que encapsula o objeto de aplicação (equivalente ao programa principal em aplicativos MFC), CConversorMFCApp, conforme mostrado na figura 19.

Figura 19: Classes usadas na implementação da versão Windows/MFC do conversor de protocolos CConversorMFCApp

CConversorMFCApp()

<<virtual>> InitInstance() CConversorMFCDlg

CConversorMFCDlg()

<<virtual>> DoDataExchange() HabilitaBotoesDNP()

AtualizaDispositivos() Send_Generic_Message() Send_RP570_Message() Send_Modbus_Message() Send_DNP_Message() Send_DB_Message()

<<virtual>> OnInitDialog() OnSysCommand() OnPaint()

OnQueryDragIcon() OnSetFunctionBtn() OnMudaSD() OnModbusSelect() OnDNPselect() OnDestroy()

OnEscolheDispositivo() OnHabilitaPolling() OnLimpaCaixas() OnEscolheFuncao() OnEscolheEndereco() OnCheckPRM() OnRP570Select() OnDBSelect()

OnEscolheFuncaoGenerica() OnTestaGenerica()

on_wm_out()

(27)

O sistema se encontra bem documentado tanto no nível de código fonte quanto no nível de projeto. A documentação reflete o estágio atual do projeto e do código fonte e está totalmente sincronizada. Para o projeto estão sendo entregues o arquivo de modelo e toda a documentação correspondente em HTML [8].

Instruções para a instalação, configuração e utilização do sistema estão contidas nos documentos [10-11]. Para que o sistema possa ser utilizado da maneira a mais fácil e flexível possível, toda a sua configuração é efetuada no banco de dados. Um servidor MySQL [11-12] dá suporte ao banco de dados. Qualquer front-end de acesso a este servidor pode ser utilizado para configurar o sistema, verificar o estado das entradas, eventos, alarmes, ou mesmo para modificar as saídas a serem enviadas aos dispositivos.

O programa gratuito MySQL Front [13] tem sido usado, para este fim.

Na implementação das classes de acesso aos bancos de dados foi utilizada a biblioteca MySQL++, também disponível gratuitamente [14], que encapsula em classes os comandos de consulta e escrita no banco de dados. Todo acesso às portas seriais foi implementado utilizando a classe PCRS232 e as especializações criadas neste projeto, como a CSerialEx.

O código usa C++ padrão em todas as suas construções, exceto na criação de múltiplas threads de execução, na utilização de objetos de sincronização entre estas threads e no acesso às portas seriais. Para estes casos, estão sendo usadas funções fornecidas pela API do sistema operacional, visto que a linguagem C++ padrão não oferece objetos padronizados que implementem estas funcionalidades. Também para a implementação da interface da versão Windows foi utilizada a biblioteca de classes MFC da Microsoft, mas esta utilização está restrita às duas classes da figura 19.

6. Considerações finais

O conversor de protocolos e os protocolos implementados foram testados utilizando-se o analisador de protocolos ASE2000, fornecido pelas empresas Applied Systems Engineering e SubNetSolutions [15]. O sistema e o protocolo DNP3 também foram testados utilizando equipamentos reais - um multimedidor M300 utilizando o protocolo MODBUS e um relé SEL 351A utilizando protocolo DNP existentes na CEMIG, efetuando- se, portanto, testes de integração [19].

Em todos estes testes, verificou-se que as funcionalidades previstas para o conversor de protocolos, tanto funcionando como escravo, quanto funcionando como mestre foram alcançadas com sucesso.

Referências

Documentos relacionados

Mas ele é ( verbo ser, no Presente do Indicativo ) apenas um gato e não tinha tido ( verbo ter, no Pretérito Mais-Que-Perfeito Simples do Indicativo ) tempo de aprender (

Conforme a classificação de risco, diante de um caso suspeito de febre de Chikungunya, o hemograma deve ser solicitado à critério médico para as formas brandas da doença e

- Sugestiva de estar relacionada à infecção congênita por STORCH: caso notificado como microcefalia E que apresente diagnóstico laboratorial específico e conclusivo para

-Não utilizar AINH (Anti-inflamatório não hormonal) ou Aspirina (acido acetilsalicílico) na fase aguda, pelo risco de complicações associados às formas graves de

Protocolo de atendimento a pacientes portadores de doença pulmonar obstrutiva crônica (DPOC) no Estado do Ceará/ Coordenadoria de Políticas de Atenção à Saúde/ Núcleo

• Após hidratação supervisionada e avaliação médica, o paciente poderá reali- zar o tratamento no domicílio e deve ser orientado para retornar diariamente à unidade de

• Os profissionais, não vacinados, de laboratório que tenham manipulado amostras clínicas que contenham o vírus influenza pandêmica (H1N1) 2009 sem o uso de

Crianças Neisseria meningitidis (meningococo), Haemophilus influenzae, Streptococcus pneumoniae