open62541 (http://open62541.org) é uma implementação de código aberto do OPC UA (OPC Unified Architecture/IEC 62541) escrita na linguagem C. A biblioteca pode ser usada com todos os principais compiladores e fornece as ferramentas necessárias para implementar clientes e servidores OPC UA dedicados ou para integrar a comunicação baseada em OPC UA em aplicativos existentes. A biblioteca open62541 é independente de plataforma: todas as funcionalidades específicas da plataforma são implementadas por meio de plug-ins trocáveis para fácil portabilidade para diferentes alvos (incorporados).
open62541 está licenciado sob a Licença Pública Mozilla v2.0 (MPLv2). Isto permite que a biblioteca open62541 seja combinada e distribuída com qualquer software proprietário. Apenas as alterações na própria biblioteca open62541 precisam ser licenciadas sob o MPLv2 quando copiadas e distribuídas. Os plugins, bem como os exemplos de servidor e cliente são de domínio público (licença CC0). Eles podem ser reutilizados sob qualquer licença e as alterações não precisam ser publicadas.
A biblioteca está disponível em fonte padrão e formato binário. Além disso, a distribuição de código-fonte de arquivo único mescla toda a biblioteca em um único arquivo .c e .h que pode ser facilmente adicionado a projetos existentes. Exemplos de implementações de servidor e cliente podem ser encontrados no diretório /examples ou mais abaixo nesta página.
open62541 implementa um SDK OPC UA com suporte para servidores, clientes e comunicação PubSub (publicar-assinar). Consulte a visão geral dos recursos para obter detalhes completos.
open62541 está licenciado sob MPLv2. Ou seja, as alterações nos arquivos MPLv2 estão sob a mesma licença de código aberto. Mas a biblioteca pode ser combinada com o desenvolvimento privado a partir de arquivos separados, mesmo se um binário estático for produzido, sem que a licença afete os arquivos privados. Consulte o documento de licença completo para obter detalhes.
O Fraunhofer IOSB emprega vários desenvolvedores do open62541 e fornece suporte comercial . Provedores de serviços adicionais no ecossistema open62541 estão listados em open62541.org.
O servidor de amostra (server_ctt) construído usando open62541 v1.0 está em conformidade com o perfil 'Micro Embedded Device Server' da OPC Foundation, suportando comunicação cliente/servidor OPC UA, assinaturas, chamadas de método e segurança (criptografia) com as políticas de segurança 'Basic128Rsa15 ', 'Basic256' e 'Basic256Sha256' e as facetas 'method server' e 'node gerenciamento'. Consulte https://open62541.org/certified-sdk para obter mais detalhes.
PubSub (UADP) é implementado em open62541. Mas o recurso não pode ser certificado neste momento (setembro de 2019) devido à falta de casos de teste e ferramentas de teste oficiais.
Durante o desenvolvimento, as Ferramentas de Teste de Conformidade (CTT) da OPC Foundation são aplicadas regularmente. A configuração e os resultados dos CTT são acompanhados em https://github.com/open62541/open62541-ctt. Os perfis OPC UA em teste regular nos CTT são atualmente:
Consulte a página open62541 Features para uma visão detalhada do suporte para as unidades de conformidade que compõem os perfis OPC UA.
Uma introdução geral ao OPC UA e à documentação do open62541 pode ser encontrada em http://open62541.org. Versões anteriores da biblioteca podem ser baixadas em https://github.com/open62541/open62541/releases.
A comunidade open62541 em geral lida com solicitações de suporte público no Github e na lista de discussão. Para discussão e suporte individual, use os seguintes canais:
Queremos promover uma comunidade aberta e acolhedora. Por favor, leve em consideração nosso código de conduta.
O ambiente de construção do open62541 é gerado via CMake. Consulte a documentação de construção para obter detalhes. Para simplificar a integração com projetos de software existentes, as fontes open62541 podem ser compactadas (amalgamadas) em uma distribuição de arquivo único, um par de arquivos open62541.c/.h
. A funcionalidade incluída na distribuição de arquivo único depende da configuração atual do CMake.
O código-fonte está estruturado da seguinte forma:
/include
): A API pública é exposta a aplicativos que usam open62541. Os cabeçalhos para implementações de plugins estão em /plugins/include
./src
): A biblioteca principal não possui dependências além dos cabeçalhos padrão C99./arch
): O suporte de arquitetura é implementado por meio do plugin EventLoop
. Isso mantém o código específico da arquitetura - por exemplo, para usar as APIs POSIX - fora da biblioteca principal. São fornecidas portas para diferentes arquiteturas (incorporadas)./plugins
): As interfaces de plugins permitem a integração com diferentes sistemas backend e bibliotecas. Por exemplo, no que diz respeito às primitivas criptográficas, armazenamento do modelo de informação, e assim por diante. Implementações padrão são fornecidas./deps
): Algumas bibliotecas adicionais são usadas por meio de submódulos git ou foram internalizadas na pasta deps/
. Mais informações sobre as bibliotecas de terceiros e suas respectivas licenças podem ser encontradas em deps/README.mdNa maioria dos sistemas, um open62541 básico requer apenas a biblioteca padrão C. Dependendo da configuração de compilação, open62541 depende de bibliotecas adicionais, como mbedTLS ou OpenSSL para criptografia.
Por ser um projeto de código aberto, novos contribuidores são incentivados a ajudar a melhorar o open62541. O arquivo CONTRIBUTING.md agrega boas práticas que esperamos para contribuições de código. A seguir estão bons pontos de partida para novos contribuidores:
Para desenvolvimento personalizado que eventualmente se tornará parte da biblioteca open62541, mantenha um dos principais mantenedores informado.
Enfatizamos a qualidade do código. As seguintes métricas de qualidade são continuamente verificadas e garantidas antes que um lançamento oficial seja feito:
O projeto estabeleceu um processo para lidar com vulnerabilidades. Consulte SECURITY.md para obter detalhes e como divulgar as descobertas de maneira responsável aos mantenedores.
Exemplos de código podem ser encontrados no diretório /examples. Para construir os exemplos, recomendamos instalar o open62541 conforme mencionado na seção anterior. Usando o compilador GCC, basta executar gcc -std=c99
(no Windows, pode ser necessário adicionar um link adicional à biblioteca de soquete ws2_32
).
#include
int main ( int argc , char * * argv )
{
/* Create a server listening on port 4840 (default) */
UA_Server * server = UA_Server_new ();
/* Add a variable node to the server */
/* 1) Define the variable attributes */
UA_VariableAttributes attr = UA_VariableAttributes_default ;
attr . displayName = UA_LOCALIZEDTEXT ( "en-US" , "the answer" );
UA_Int32 myInteger = 42 ;
UA_Variant_setScalar ( & attr . value , & myInteger , & UA_TYPES [ UA_TYPES_INT32 ]);
/* 2) Define where the node shall be added with which browsename */
UA_NodeId newNodeId = UA_NODEID_STRING ( 1 , "the.answer" );
UA_NodeId parentNodeId = UA_NS0ID ( OBJECTSFOLDER );
UA_NodeId parentReferenceNodeId = UA_NS0ID ( ORGANIZES );
UA_NodeId variableType = UA_NODEID_NULL ; /* take the default variable type */
UA_QualifiedName browseName = UA_QUALIFIEDNAME ( 1 , "the answer" );
/* 3) Add the node */
UA_Server_addVariableNode ( server , newNodeId , parentNodeId ,
parentReferenceNodeId , browseName ,
variableType , attr , NULL , NULL );
/* Run the server (until ctrl-c interrupt) */
UA_StatusCode status = UA_Server_runUntilInterrupt ( server );
/* Clean up */
UA_Server_delete ( server );
return status == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE ;
}
#include
#include
#include
int main ( int argc , char * argv [])
{
/* Create a client and connect */
UA_Client * client = UA_Client_new ();
UA_ClientConfig_setDefault ( UA_Client_getConfig ( client ));
UA_StatusCode status = UA_Client_connect ( client , "opc.tcp://localhost:4840" );
if ( status != UA_STATUSCODE_GOOD ) {
UA_Client_delete ( client );
return status ;
}
/* Read the value attribute of the node. UA_Client_readValueAttribute is a
* wrapper for the raw read service available as UA_Client_Service_read. */
UA_Variant value ; /* Variants can hold scalar values and arrays of any type */
UA_Variant_init ( & value );
status = UA_Client_readValueAttribute ( client , UA_NODEID_STRING ( 1 , "the.answer" ), & value );
if ( status == UA_STATUSCODE_GOOD &&
UA_Variant_hasScalarType ( & value , & UA_TYPES [ UA_TYPES_INT32 ])) {
printf ( "the value is: %in" , * ( UA_Int32 * ) value . data );
}
/* Clean up */
UA_Variant_clear ( & value );
UA_Client_delete ( client ); /* Disconnects the client internally */
return status == UA_STATUSCODE_GOOD ? EXIT_SUCCESS : EXIT_FAILURE ;
}