1
0
mirror of https://github.com/mainflux/mainflux.git synced 2025-05-14 19:29:11 +08:00
Manuel Imperiale e16a025fba
MF-886 - Add OPC-UA adapter (#878)
* NOISSUE- Add OPC-UA adapter

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* NOISSUE - Add opc-adapter PoC, docker and vendor

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Convert OPC messages to SenML

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Add gopcua package

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* lora-adapter typo

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Add OPC Reader

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Typo fix

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Typo fix

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Update copyright headers

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix reviews

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix reviews

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Add opc config

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Add all opc envars in the config

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Config typo

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Add route map

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Use opcua package instead of opc

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix OPCUA typo

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Rm MQTT sub

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Move interefaces to root

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Fix revieews and typo

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Update Gopkg.toml

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>

* Add all envars into .env

Signed-off-by: Manuel Imperiale <manuel.imperiale@gmail.com>
2019-10-22 17:44:19 +02:00

146 lines
4.7 KiB
Go

// Copyright 2018-2019 opcua authors. All rights reserved.
// Use of this source code is governed by a MIT-style license that can be
// found in the LICENSE file.
package ua
import (
"github.com/gopcua/opcua/errors"
"github.com/gopcua/opcua/id"
)
// eotypes contains all known extension objects.
var eotypes = NewTypeRegistry()
// init registers known built-in extension objects.
func init() {
RegisterExtensionObject(NewNumericNodeID(0, id.AnonymousIdentityToken_Encoding_DefaultBinary), new(AnonymousIdentityToken))
RegisterExtensionObject(NewNumericNodeID(0, id.UserNameIdentityToken_Encoding_DefaultBinary), new(UserNameIdentityToken))
RegisterExtensionObject(NewNumericNodeID(0, id.X509IdentityToken_Encoding_DefaultBinary), new(X509IdentityToken))
RegisterExtensionObject(NewNumericNodeID(0, id.IssuedIdentityToken_Encoding_DefaultBinary), new(IssuedIdentityToken))
RegisterExtensionObject(NewNumericNodeID(0, id.ServerStatusDataType_Encoding_DefaultBinary), new(ServerStatusDataType))
RegisterExtensionObject(NewNumericNodeID(0, id.DataChangeNotification_Encoding_DefaultBinary), new(DataChangeNotification))
RegisterExtensionObject(NewNumericNodeID(0, id.ReadRawModifiedDetails_Encoding_DefaultBinary), new(ReadRawModifiedDetails))
RegisterExtensionObject(NewNumericNodeID(0, id.HistoryData_Encoding_DefaultBinary), new(HistoryData))
RegisterExtensionObject(NewNumericNodeID(0, id.SubscriptionDiagnosticsDataType_Encoding_DefaultBinary), new(SubscriptionDiagnosticsDataType))
}
// RegisterExtensionObject registers a new extension object type.
// It panics if the type or the id is already registered.
func RegisterExtensionObject(typeID *NodeID, v interface{}) {
if err := eotypes.Register(typeID.String(), v); err != nil {
panic("Extension object " + err.Error())
}
}
// These flags define the value type of an ExtensionObject.
// They cannot be combined.
const (
ExtensionObjectEmpty = 0
ExtensionObjectBinary = 1
ExtensionObjectXML = 2
)
// ExtensionObject is encoded as sequence of bytes prefixed by the NodeId of its DataTypeEncoding
// and the number of bytes encoded.
//
// Specification: Part 6, 5.2.2.15
type ExtensionObject struct {
EncodingMask uint8
TypeID *ExpandedNodeID
Value interface{}
}
func NewExtensionObject(value interface{}) *ExtensionObject {
e := &ExtensionObject{
TypeID: ExtensionObjectTypeID(value),
Value: value,
}
e.UpdateMask()
return e
}
func (e *ExtensionObject) Decode(b []byte) (int, error) {
buf := NewBuffer(b)
e.TypeID = new(ExpandedNodeID)
buf.ReadStruct(e.TypeID)
e.EncodingMask = buf.ReadByte()
if e.EncodingMask == ExtensionObjectEmpty {
return buf.Pos(), buf.Error()
}
length := buf.ReadUint32()
if length == 0 || length == 0xffffffff || buf.Error() != nil {
return buf.Pos(), buf.Error()
}
body := NewBuffer(buf.ReadN(int(length)))
if buf.Error() != nil {
return buf.Pos(), buf.Error()
}
if e.EncodingMask == ExtensionObjectXML {
e.Value = new(XMLElement)
body.ReadStruct(e.Value)
return buf.Pos(), body.Error()
}
typeID := e.TypeID.NodeID.String()
e.Value = eotypes.New(typeID)
if e.Value == nil {
return buf.Pos(), errors.Errorf("invalid extension object with id %s", typeID)
}
body.ReadStruct(e.Value)
return buf.Pos(), body.Error()
}
func (e *ExtensionObject) Encode() ([]byte, error) {
buf := NewBuffer(nil)
if e == nil {
e = &ExtensionObject{TypeID: NewTwoByteExpandedNodeID(0), EncodingMask: ExtensionObjectEmpty}
}
buf.WriteStruct(e.TypeID)
buf.WriteByte(e.EncodingMask)
if e.EncodingMask == ExtensionObjectEmpty {
return buf.Bytes(), buf.Error()
}
body := NewBuffer(nil)
body.WriteStruct(e.Value)
if body.Error() != nil {
return nil, body.Error()
}
buf.WriteUint32(uint32(body.Len()))
buf.Write(body.Bytes())
return buf.Bytes(), buf.Error()
}
func (e *ExtensionObject) UpdateMask() {
if e.Value == nil {
e.EncodingMask = ExtensionObjectEmpty
} else if _, ok := e.Value.(*XMLElement); ok {
e.EncodingMask = ExtensionObjectXML
} else {
e.EncodingMask = ExtensionObjectBinary
}
}
func ExtensionObjectTypeID(v interface{}) *ExpandedNodeID {
switch v.(type) {
case *AnonymousIdentityToken:
return NewFourByteExpandedNodeID(0, id.AnonymousIdentityToken_Encoding_DefaultBinary)
case *UserNameIdentityToken:
return NewFourByteExpandedNodeID(0, id.UserNameIdentityToken_Encoding_DefaultBinary)
case *X509IdentityToken:
return NewFourByteExpandedNodeID(0, id.X509IdentityToken_Encoding_DefaultBinary)
case *IssuedIdentityToken:
return NewFourByteExpandedNodeID(0, id.IssuedIdentityToken_Encoding_DefaultBinary)
case *ServerStatusDataType:
return NewFourByteExpandedNodeID(0, id.ServerStatusDataType_Encoding_DefaultBinary)
default:
return NewTwoByteExpandedNodeID(0)
}
}