Skip to content

Commit

Permalink
Merge pull request #14 from boschrexroth/release/2.5
Browse files Browse the repository at this point in the history
Release/2.5
  • Loading branch information
albrecht-j authored Dec 4, 2024
2 parents 5a9f46e + 1a86453 commit 91d8485
Show file tree
Hide file tree
Showing 96 changed files with 8,913 additions and 49 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ jobs:
sudo apt-get update
sudo apt-get install -y libsystemd-dev
sudo apt install pkg-config
wget https://github.com/boschrexroth/ctrlx-automation-sdk/releases/download/3.2.0/ctrlx-datalayer-2.7.5.deb
sudo apt-get install -y -f ./ctrlx-datalayer-2.7.5.deb
wget https://github.com/boschrexroth/ctrlx-automation-sdk/releases/download/3.4.0/ctrlx-datalayer-2.8.6.deb
sudo apt-get install -y -f ./ctrlx-datalayer-2.8.6.deb
- name: Set up Go
uses: actions/setup-go@v5
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ GOOS := $(shell go env GOOS)
GOARCH := $(shell go env GOARCH)
BUILD := build/public/$(GOOS)_$(GOARCH)

SDK_RELEASE_VERSION := 3.2.0
DATALAYER_DEB_FILE_VERSION := 2.7.5
SDK_RELEASE_VERSION := 3.4.0
DATALAYER_DEB_FILE_VERSION := 2.8.6

.PHONY: all go-dep apt-dep lint vet test test-coverage build clean

Expand Down
23 changes: 11 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
# ctrlX Data Layer client and provider library for golang

This project provides:

1. ctrlX Data Layer access via Golang

It wraps the original ctrlX Data Layer written in C++.
Expand All @@ -10,25 +10,24 @@ This project provides:

2. Server-Sent Events(SSE) Client

Server-Sent Events is HTTP/HTTP2 common standard, the SSE server pushes the update to the client, the client receives automatic updates via HTTP connection.
Server-Sent Events is HTTP/HTTP2 common standard, the SSE server pushes the update to the client, the client receives automatic updates via HTTP connection.

ctrlX Data Layer provides a SSE Server, which makes the data on the Data Layer accessible to the web application.
ctrlX Data Layer provides a SSE Server, which makes the data on the Data Layer accessible to the web application.

The SSE client library can be used to connect to the SSE Server of the ctrlX Data Layer running on the ctrlX Device. It is possible to subscribe to nodes on the server and the server will automatically send new updates on value changes.

You can find documentation here [GoDoc](https://pkg.go.dev/github.com/boschrexroth/ctrlx-datalayer-golang/v2/pkg/sseclient)

3. Token handling

JSON Web Token is used for authentification in ctrlX Core.
JSON Web Token is used for authentification in ctrlX Core.

The token library can be used to get token from ctrlX Core and later on check if the token is still valid.
The token library can be used to get token from ctrlX Core and later on check if the token is still valid.

You can find documentation here [GoDoc](https://pkg.go.dev/github.com/boschrexroth/ctrlx-datalayer-golang/v2/pkg/token)

## Status


![Make Test](https://github.com/boschrexroth/ctrlx-datalayer-golang/actions/workflows/main.yml/badge.svg)

## Usage
Expand All @@ -44,8 +43,8 @@ sudo apt-get install libsystemd-dev libsystemd-dev:arm64
Check the current [ctrlx Data Layer](https://github.com/boschrexroth/ctrlx-automation-sdk/releases) debian package, download and install this, see example.

```bash
wget https://github.com/boschrexroth/ctrlx-automation-sdk/releases/download/3.2.0/ctrlx-datalayer-2.7.5.deb
sudo dpkg -i ctrlx-datalayer-2.7.5.deb
wget https://github.com/boschrexroth/ctrlx-automation-sdk/releases/download/3.4.0/ctrlx-datalayer-2.8.6.deb
sudo dpkg -i ctrlx-datalayer-2.8.6.deb
```

### Integrate in you project
Expand All @@ -60,16 +59,16 @@ Copyright © 2022 Bosch Rexroth AG. All rights reserved.

<https://www.boschrexroth.com>

Bosch Rexroth AG
Bgm.-Dr.-Nebel-Str. 2
97816 Lohr am Main
Bosch Rexroth AG
Bgm.-Dr.-Nebel-Str. 2
97816 Lohr am Main
GERMANY

## Licenses

MIT License

Copyright (c) 2021-2022 Bosch Rexroth AG
Copyright (c) 2021-2024 Bosch Rexroth AG

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
10 changes: 10 additions & 0 deletions pkg/datalayer/nodeHandler.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,3 +68,13 @@ void nodeCallbackOnMetadata(void *userdata, char *address, TYPE_CB cb, TYPE_CBDA
{
nodeCallbackGo(userdata, address, NULL, cb, (uint64_t)cbdata, NODE_ACTION_ON_METADATA);
}

void nodeCallbackSubscription(void *userdata, DLR_SUBSCRIPTION subscription, char *address)
{
nodeCallbackSubGo(userdata, subscription, address, NODE_ACTION_ON_SUBSCRIPTION);
}

void nodeCallbackUnsubscription(void *userdata, DLR_SUBSCRIPTION subscription, char *address)
{
nodeCallbackSubGo(userdata, subscription, address, NODE_ACTION_ON_UNSUBSCRIPTION);
}
54 changes: 46 additions & 8 deletions pkg/datalayer/nodeHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ typedef enum NODE_ACTION {
NODE_ACTION_ON_READ,
NODE_ACTION_ON_WRITE,
NODE_ACTION_ON_METADATA,
NODE_ACTION_ON_SUBSCRIPTION,
NODE_ACTION_ON_UNSUBSCRIPTION
}NODE_ACTION;
extern void callCallbackC(TYPE_CB cb, uint64_t cbdata, DLR_RESULT result, DLR_VARIANT data);
Expand All @@ -48,7 +50,11 @@ extern void nodeCallbackOnRemove(void* userdata, char* address, TYPE_CB cb, TYPE
extern void nodeCallbackOnBrowse(void* userdata, char* address, TYPE_CB cb, TYPE_CBDATA cbdata);
extern void nodeCallbackOnRead(void* userdata, char* address, DLR_VARIANT data, TYPE_CB cb, TYPE_CBDATA cbdata);
extern void nodeCallbackOnWrite(void* userdata, char* address, DLR_VARIANT data, TYPE_CB cb, TYPE_CBDATA cbdata);
extern void nodeCallbackOnMetadata(void* userdata, char* address, TYPE_CB cb, TYPE_CBDATA cbdata);*/
extern void nodeCallbackOnMetadata(void* userdata, char* address, TYPE_CB cb, TYPE_CBDATA cbdata);
extern void nodeCallbackSubscription(void *userdata, DLR_SUBSCRIPTION subscription, char *address);
extern void nodeCallbackUnsubscription(void *userdata, DLR_SUBSCRIPTION subscription, char *address);
*/
import "C"
import (
"sync"
Expand All @@ -60,12 +66,14 @@ type nodeAction C.enum_NODE_ACTION

// nodeAction enum definition
const (
nodeActionOnCreate nodeAction = C.NODE_ACTION_ON_CREATE
nodeActionOnRemove nodeAction = C.NODE_ACTION_ON_REMOVE
nodeActionOnBrowse nodeAction = C.NODE_ACTION_ON_BROWSE
nodeActionOnRead nodeAction = C.NODE_ACTION_ON_READ
nodeActionOnWrite nodeAction = C.NODE_ACTION_ON_WRITE
nodeActionOnMetadata nodeAction = C.NODE_ACTION_ON_METADATA
nodeActionOnCreate nodeAction = C.NODE_ACTION_ON_CREATE
nodeActionOnRemove nodeAction = C.NODE_ACTION_ON_REMOVE
nodeActionOnBrowse nodeAction = C.NODE_ACTION_ON_BROWSE
nodeActionOnRead nodeAction = C.NODE_ACTION_ON_READ
nodeActionOnWrite nodeAction = C.NODE_ACTION_ON_WRITE
nodeActionOnMetadata nodeAction = C.NODE_ACTION_ON_METADATA
nodeActionOnSubsciption nodeAction = C.NODE_ACTION_ON_SUBSCRIPTION
nodeActionOnUnsubsciption nodeAction = C.NODE_ACTION_ON_UNSUBSCRIPTION
)

// nodeCallbackData type
Expand Down Expand Up @@ -96,7 +104,22 @@ func nodeCallbackGo(cuserdata unsafe.Pointer, caddress *C.char, cdata C.DLR_VARI
}
}

// getNodeCallbacksC get struct with all C callbacks
//export nodeCallbackSubGo
func nodeCallbackSubGo(cuserdata unsafe.Pointer, sub C.DLR_SUBSCRIPTION, caddress *C.char, action C.int) {
var i int = *(*int)(cuserdata)
var userdata *nodeUserData = nodeLookup(i)
address := C.GoString(caddress)
switch nodeAction(action) {
case nodeActionOnSubsciption:
userdata.channels.OnSubscribe <- ProviderNodeSubscription{Address: address, Subsciption: &ProviderSubscription{this: sub}}
case nodeActionOnUnsubsciption:
userdata.channels.OnUnsubscribe <- ProviderNodeSubscription{Address: address, Subsciption: &ProviderSubscription{this: sub}}
default:
panic("Unknown action type in callback")
}
}

// getNodeCallbacksC get struct with subset of the C callbacks
func getNodeCallbacksC(userdata unsafe.Pointer) C.DLR_PROVIDER_NODE_CALLBACKS {
return C.DLR_PROVIDER_NODE_CALLBACKS{
userData: userdata,
Expand All @@ -109,6 +132,21 @@ func getNodeCallbacksC(userdata unsafe.Pointer) C.DLR_PROVIDER_NODE_CALLBACKS {
}
}

// getNodeSubCallbacksC get struct with all C callbacks
func getNodeSubCallbacksC(userdata unsafe.Pointer) C.DLR_PROVIDER_NODE_CALLBACKS {
return C.DLR_PROVIDER_NODE_CALLBACKS{
userData: userdata,
onCreate: (*[0]byte)(C.nodeCallbackOnCreate),
onRemove: (*[0]byte)(C.nodeCallbackOnRemove),
onBrowse: (*[0]byte)(C.nodeCallbackOnBrowse),
onRead: (*[0]byte)(C.nodeCallbackOnRead),
onWrite: (*[0]byte)(C.nodeCallbackOnWrite),
onMetadata: (*[0]byte)(C.nodeCallbackOnMetadata),
onSubscribe: (*[0]byte)(C.nodeCallbackSubscription),
onUnsubscribe: (*[0]byte)(C.nodeCallbackUnsubscription),
}
}

// getNodeUserdata store Go channels in userdata of C callback
func getNodeUserdata(channels ProviderNodeChannels) unsafe.Pointer {
userdata := &nodeUserData{channels: channels}
Expand Down
113 changes: 113 additions & 0 deletions pkg/datalayer/notifyitempublish.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
// MIT License
//
// Copyright (c) 2021-2024 Bosch Rexroth AG
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.

package datalayer

import (
"time"

fbs "github.com/boschrexroth/ctrlx-datalayer-golang/v2/pkg/fbs/comm/datalayer"
flatbuffers "github.com/google/flatbuffers/go"
)

// NotifyItemPublish interface for publish subscription items.
type NotifyItemPublish struct {
data *Variant
info *Variant
notifyInfo *fbs.NotifyInfoT
}

// NewNotifyItemPublish creates a NotifyItemPublish
// Parameter address is the address of the provider node.
func NewNotifyItemPublish(address string) *NotifyItemPublish {
i := &NotifyItemPublish{
data: NewVariant(),
info: NewVariant(),
notifyInfo: &fbs.NotifyInfoT{
Node: address,
Timestamp: toFiletime(time.Now()),
NotifyType: fbs.NotifyTypeData,
SequenceNumber: 0,
},
}
return i
}

// deleteNotifyItemPublish removes a NotifyItemPublish.
// Parameter n is an instance of the NotifyItemPublish.
func deleteNotifyItemPublish(n *NotifyItemPublish) {
if n == nil {
return
}
DeleteVariant(n.data)
DeleteVariant(n.info)
}

// DeleteNotifyItemsPublish removes a lit of NotifyItemPublish.
// Parameter s is list of the NotifyItemPublish.
func DeleteNotifyItemsPublish(l []*NotifyItemPublish) {
for _, n := range l {
deleteNotifyItemPublish(n)
}
}

// GetData gets the data of the notify item.
// It returns the variant.
func (i *NotifyItemPublish) GetData() *Variant {
return i.data
}

// GetInfo gets the info of the notify item.
// containing notify_info.fbs (address, timestamp, type, ...).
// It returns the variant
func (i *NotifyItemPublish) GetInfo() *Variant {
builder := flatbuffers.NewBuilder(4096)
niPack := i.notifyInfo.Pack(builder)
builder.Finish(niPack)
i.info.SetFlatbuffers(builder.FinishedBytes())
return i.info
}

// SetNotifyType sets the NotifyType of the notify_info.fbs.
func (i *NotifyItemPublish) SetNotifyType(n fbs.NotifyType) {
i.notifyInfo.NotifyType = n
}

// SetTimestamp sets a time.Time value since January 1, 1970 UTC of the notify_info.fbs.
func (i *NotifyItemPublish) SetTimestamp(t time.Time) {
i.notifyInfo.Timestamp = toFiletime(t)
}

// SetEventType sets eventtype of the notify_info.fbs.
func (i *NotifyItemPublish) SetEventType(e string) {
i.notifyInfo.EventType = e
}

// SetSequenceNumber sets sequence number of the notify_info.fbs.
func (i *NotifyItemPublish) SetSequenceNumber(n uint64) {
i.notifyInfo.SequenceNumber = n
}

// SetSequenceNumber sets source name of the notify_info.fbs.
func (i *NotifyItemPublish) SetSourceName(s string) {
i.notifyInfo.SourceName = s
}
44 changes: 44 additions & 0 deletions pkg/datalayer/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,3 +129,47 @@ func (p *Provider) GetToken() *Variant {
ptr := C.DLR_providerGetToken(p.this)
return &Variant{this: ptr}
}

// GetRegisteredType get the variant of a registered type
// Parameter address is address of the type to get type (no wildcards allowed).
// It returns the status of function call and variant to stored type (Result, Variant).
func (p *Provider) GetRegisteredType(address string) (Result, *Variant) {
caddress := C.CString(address)
defer C.free(unsafe.Pointer(caddress))
data := NewVariant()
r := Result(C.DLR_providerGetRegisteredType(p.this, caddress, data.this))
return r, data
}

// GetRegisteredNodePaths return the current registered node paths.
// It returns the status of function call and list of registered node paths.
func (p *Provider) GetRegisteredNodePaths() (Result, []string) {
data := NewVariant()
defer DeleteVariant(data)
r := Result(C.DLR_providerGetRegisteredNodePaths(p.this, data.this))
if r != ResultOk {
return r, []string{}
}
return r, data.GetArrayString()
}

// GetRejectedNodePaths return the current rejected node paths.
// It returns the status of function call and list of rejected node paths.
func (p *Provider) GetRejectedNodePaths() (Result, []string) {
data := NewVariant()
defer DeleteVariant(data)
r := Result(C.DLR_providerGetRejectedNodePaths(p.this, data.this))
if r != ResultOk {
return r, []string{}
}
return r, data.GetArrayString()
}

// PublishEvent publishes an event
// Parameter data is the payload data of the event. Has to match the type, that is given in the notifyInfo.
// Parameter eventtype contains additional info about the event with type event_info.fbs.
// It returns the status of function call.
func (p *Provider) PublishEvent(data, eventtype *Variant) Result {
r := Result(C.DLR_providerPublishEvent(p.this, data.this, eventtype.this))
return r
}
Loading

0 comments on commit 91d8485

Please sign in to comment.