Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Manufacturing Technology >> Tecnologia industrial

Popular Classe C++ a partir de XML Usando IXMLSerializable no PLCnext

Resumo

Você sabia que as PLCnext Common Classes têm suporte nativo para serialização XML? Este artigo mostra como usar a interface IXmlSerializable para popular dados em uma classe C++.

Encontre a descrição da Interface na documentação da API das PLCnext Common Classes.

Requisitos

Este artigo foi escrito com:

PLCnext Firmware: 2020.6 LTS
PLCnext C++ SDK para Linux 64 Bit 2020.6 LTS

Os Dados

Queremos popular nossa classe com o seguinte arquivo de configuração:

<?xml version="1.0" encoding="UTF-8"?>
<MyConfigDocument schemaVersion="1.0">
  <Server dnsName="server.domain.tld" />
  <FileList>
    <File path="$ARP_DATA_DIR$/Services/MyComponent/file1.txt" />
    <File path="$ARP_DATA_DIR$/Services/MyComponent/file2.txt" />
  </FileList>
</MyConfigDocument>

A notação $ARP_DATA_DIR$ é placeholder para variável de ambiente, neste caso ARP_DATA_DIR. Encontre as variáveis de ambiente Arp definidas no arquivo de configuração do dispositivo no target /etc/plcnext/Device.acf.settings.

Para ler dados de arquivo XML, devemos implementar interface IXMLSerializable para nossa classe. Para simplificar, nossa classe tem apenas dois elementos: nome DNS e vetor de caminhos de arquivo.

#pragma once
#include "Arp/System/Core/Arp.h"
#include "Arp/System/Commons/Xml/IXmlSerializable.hpp"
#include <vector>

namespace MyComponent {
  class MyConfiguration : public Arp::System::Commons::Xml::IXmlSerializable {
  public:
    MyConfiguration() = default;
    ~MyConfiguration() = default;

    // Interface IXMLSerializable
  public:
    void ReadXml(Arp::System::Commons::Xml::XmlReader& reader,
                 Arp::System::Commons::Xml::XmlSerializationContext& context) override;
    void WriteXml(Arp::System::Commons::Xml::XmlWriter& writer,
                  Arp::System::Commons::Xml::XmlSerializationContext& context) override;

    // Os dados
  public:
    Arp::String DnsName{""};
    std::vector<Arp::String> FileList;

    // Métodos auxiliares
  private:
    void readFileList(Arp::System::Commons::Xml::XmlReader& reader,
                      Arp::System::Commons::Xml::XmlSerializationContext& context);
    void readFile(Arp::System::Commons::Xml::XmlReader& reader,
                  Arp::System::Commons::Xml::XmlSerializationContext& context);
  };
} // namespace MyComponent

Implementação

Devemos implementar os métodos ReadXml e WriteXml.

O método WriteXml é direto, não queremos escrever, apenas ler dados do XML. O método ReadXml é chamado quando queremos ler dados do XML.

#include "MyConfiguration.hpp"
namespace MyComponent {
  void MyConfiguration::WriteXml(Arp::System::Commons::Xml::XmlWriter& writer,
                                 Arp::System::Commons::Xml::XmlSerializationContext& context) {
    // sem operação
    return;
  }

  void MyConfiguration::ReadXml(Arp::System::Commons::Xml::XmlReader& reader,
                                Arp::System::Commons::Xml::XmlSerializationContext& context) {
    Arp::String elementName;
    while (reader.TryReadStartElement(elementName)) {
      if (elementName == Arp::System::Commons::Xml::XmlSerializationContext::IncludesXmlName) {
        context.ReadIncludesElement(reader);
      } else if (elementName == "Server") {
        this->DnsName = reader.GetAttributeValue<Arp::String>("dnsName");
        reader.ReadEndElement();
      } else if (elementName == "FileList") {
        this->readFileList(reader, context);
      } else {
        context.InvalidXmlElementOccurs(reader, elementName);
        reader.ReadEndElement();
      }
    }
  }

  void MyConfiguration::readFileList(Arp::System::Commons::Xml::XmlReader& reader,
                                     Arp::System::Commons::Xml::XmlSerializationContext& context) {
    if (reader.IsEmptyElement()){
      return;
    }
    if (reader.ReadToDescendant("File")) {
      this->readFile(reader, context);
      while (reader.ReadToNextSibling("File")) {
        this->readFile(reader, context);
      }
    } else {
      reader.ReadEndElement();
    }
  }

  void MyConfiguration::readFile(Arp::System::Commons::Xml::XmlReader& reader,
                                 Arp::System::Commons::Xml::XmlSerializationContext& context) {
    // Use 'context.ResolvePath' para substituir placeholders no path
    auto file = Arp::String(context.ResolvePath(reader.GetAttributeValue<Arp::String>("path")));
    this->FileList.push_back(file);
    reader.ReadEndElement();
  }
} // namespace MyComponent

Ler os dados

Agora podemos usar nossa classe com a classe XMLConfigDocument no método LoadConfig para carregar dados na classe.

void MyComponent::LoadConfig() {
  // carregar config do projeto aqui
  using namespace Arp::System::Commons;
  this->log.Info("LoadConfig");
  // Primeiro argumento deve corresponder ao nome do elemento raiz XML.
  // Nossa instância MyConfiguration this->config será populada.
  Xml::XmlConfigDocument configDoc("MyConfigDocument", this->config);
  if (!Io::File::Exists(this->settingsPath)) {
    this->log.Error("Arquivo de configuração '{}' não existe.", this->settingsPath);
    return;
  }
  try {
    configDoc.Load(this->settingsPath);
  } catch (const Arp::Exception& e) {
    this->log.Error(e.GetMessage());
    throw InvalidConfigException(e.GetMessage());
  }
}

Tecnologia industrial

  1. Usando a Interface de Linha de Comando com SPICE
  2. Como Tecnologia Está Transformando Manufatura: Da Impressão 3D a Gêmeos Digitais
  3. Dominando Java BufferedReader: Manipulação Eficiente de Streams de Caracteres
  4. Dominando Operações de Arquivo em Java com java.io – Criação, Leitura, Escrita e Exclusão
  5. Interface vs Classe Abstrata em Java: Como Escolher a Abstração Certa
  6. Entendendo Interfaces em Java: Definições, Usos e Boas Práticas
  7. Escolhendo o Motor à Prova de Explosão Certo: Guia Abrangente
  8. Tipos de Matrizes na Manufatura: Estampagem, Trefilação e Fundição Explicados
  9. Como Pontos de Teste Melhoram Testes de PCB e Eficiência de Produção
  10. Como a Automação Está Transformando a Manufatura: Aumentando Eficiência e Cortando Custos