Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add idmvs mapper #97

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions mappers/idmvs/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
FROM ubuntu:20.04
WORKDIR /usr/local/bin
COPY ./res /usr/local/res
COPY ./bin/idmvs /usr/local/bin/idmvs
ENTRYPOINT ["./idmvs", "--v", "4"]
36 changes: 36 additions & 0 deletions mappers/idmvs/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
SHELL := /bin/bash

curr_dir := $(patsubst %/,%,$(dir $(abspath $(lastword $(MAKEFILE_LIST)))))
rest_args := $(wordlist 2, $(words $(MAKECMDGOALS)), $(MAKECMDGOALS))
$(eval $(rest_args):;@:)

help:
#
# Usage:
# make template : create a mapper based on a template.
# make mapper {mapper-name} <action> <parameter>: execute mapper building process.
# make all : execute building process to all mappers.
#
# Actions:
# - mod, m : download code dependencies.
# - lint, l : verify code via go fmt and `golangci-lint`.
# - build, b : compile code.
# - package, p : package docker image.
# - test, t : run unit tests.
# - clean, c : clean output binary.
#
# Parameters:
# ARM : true or undefined
# ARM64 : true or undefined
#
# Example:
# - make mapper idmvs ARM64=true : execute `build` "idmvs" mapper for ARM64.
# - make mapper idmvs test : execute `test` "idmvs" mapper.
@echo

make_rules := $(shell ls $(curr_dir)/hack/make-rules | sed 's/.sh//g')
$(make_rules):
@$(curr_dir)/hack/make-rules/[email protected] $(rest_args)

.DEFAULT_GOAL := help
.PHONY: $(make_rules) build test package
12 changes: 12 additions & 0 deletions mappers/idmvs/cmd/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package main

import (
"github.com/kubeedge/mappers-go/mapper-sdk-go/pkg/service"
"github.com/kubeedge/mappers-go/mappers/idmvs/driver"
)

// main IDMVS device program entry
func main() {
gd := &driver.IDMVS{}
service.Bootstrap("IDMVS", gd)
}
167 changes: 167 additions & 0 deletions mappers/idmvs/driver/driver.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
package driver

import (
"encoding/json"
"fmt"
"net"
"strconv"
"strings"
"sync"
"unsafe"
)

// IDMVSProtocolConfig is the protocol config structure.
type IDMVSProtocolConfig struct {
ProtocolName string `json:"protocolName"`
ProtocolConfigData `json:"configData"`
}
// ProtocolConfigData is the protocol config data structure.
type ProtocolConfigData struct {
}

// IDMVSProtocolCommonConfig is the protocol common config structure.
type IDMVSProtocolCommonConfig struct {
CommonCustomizedValues `json:"customizedValues"`
}
// CommonCustomizedValues is the customized values structure.
type CommonCustomizedValues struct {
Port int `json:"TCPport"`
}
// IDMVSVisitorConfig is the visitor config structure.
type IDMVSVisitorConfig struct {
ProtocolName string `json:"protocolName"`
VisitorConfigData `json:"configData"`
}

// VisitorConfigData is the visitor config data structure.
type VisitorConfigData struct {
}

// IDMVS Realize the structure
type IDMVS struct {
mutex sync.Mutex
protocolConfig IDMVSProtocolConfig
protocolCommonConfig IDMVSProtocolCommonConfig
visitorConfig IDMVSVisitorConfig
listeners map[int]*IDMVSInstance
}

// IDMVSInstance is the instance structure
type IDMVSInstance struct {
server net.Listener
codeValue string
status bool
reportTimes int
}

// InitDevice Sth that need to do in the first
// If you need mount a persistent connection, you should provide parameters in configmap's protocolCommon.
// and handle these parameters in the following function
func (d *IDMVS) InitDevice(protocolCommon []byte) (err error) {
if protocolCommon != nil {
if err = json.Unmarshal(protocolCommon, &d.protocolCommonConfig); err != nil {
fmt.Printf("Unmarshal ProtocolCommonConfig error: %v\n", err)
return err
}
}
d.connect()
return nil
}

// SetConfig Parse the configmap's raw json message
// In the case of high concurrency, d.mutex helps you get the correct value
func (d *IDMVS) SetConfig(protocolCommon, visitor, protocol []byte) (port int, err error) {
d.mutex.Lock()
defer d.mutex.Unlock()
if protocolCommon != nil {
if err = json.Unmarshal(protocolCommon, &d.protocolCommonConfig); err != nil {
fmt.Printf("Unmarshal protocolCommonConfig error: %v\n", err)
return 0, err
}
}
if visitor != nil {
if err = json.Unmarshal(visitor, &d.visitorConfig); err != nil {
fmt.Printf("Unmarshal visitorConfig error: %v\n", err)
return 0, err
}
}
if protocol != nil {
if err = json.Unmarshal(protocol, &d.protocolConfig); err != nil {
fmt.Printf("Unmarshal protocolConfig error: %v\n", err)
return 0, err
}
}
return d.protocolCommonConfig.Port, nil
}

// ReadDeviceData is an interface that reads data from a specific device, data is a type of string
func (d *IDMVS) ReadDeviceData(protocolCommon, visitor, protocol []byte) (data interface{}, err error) {
// Parse raw json message to get a IDMVS instance
port, err := d.SetConfig(protocolCommon, visitor, protocol)
if err != nil {
return nil, err
}
if d.listeners[port].reportTimes == 0 {
return "NoRead", nil
}

d.listeners[port].reportTimes--
return d.listeners[port].codeValue, nil
}

// WriteDeviceData is an interface that write data to a specific device, data's DataType is Consistent with configmap
func (d *IDMVS) WriteDeviceData(data interface{}, protocolCommon, visitor, protocol []byte) (err error) {
return nil
}

// StopDevice is an interface to disconnect a specific device
// This function is called when mapper stops serving
func (d *IDMVS) StopDevice() (err error) {
return nil
}

// GetDeviceStatus is an interface to get the device status true is OK , false is DISCONNECTED
func (d *IDMVS) GetDeviceStatus(protocolCommon, visitor, protocol []byte) (status bool) {
port, err := d.SetConfig(protocolCommon, visitor, protocol)
if err != nil {
return false
}
return d.listeners[port].status
}

func (d *IDMVS) connect() {
if d.listeners == nil {
d.listeners = make(map[int]*IDMVSInstance)
}
clientPort := strconv.Itoa(d.protocolCommonConfig.Port)
address := fmt.Sprintf("0.0.0.0:%s", clientPort)
d.listeners[d.protocolCommonConfig.Port] = new(IDMVSInstance)
var err error
d.listeners[d.protocolCommonConfig.Port].server, err = net.Listen("tcp", address)
if err != nil {
fmt.Printf("Listen %s server failed,err:%s\n", address, err)
return
}
go func() {
conn, err := d.listeners[d.protocolCommonConfig.Port].server.Accept()
if err != nil {
fmt.Println("Listen.Accept failed,err:", err)
}
defer conn.Close()
for {
buf := make([]byte, 256)
n, err := conn.Read(buf[:])
if err != nil {
fmt.Println("Read from tcp server failed,err:", err)
d.listeners[d.protocolCommonConfig.Port].status = false
} else {
data := buf[:n]
barCode := *(*string)(unsafe.Pointer(&data))
barCode = strings.TrimRight(strings.TrimLeft(barCode, "<p>"), "</p>")
d.listeners[d.protocolCommonConfig.Port].codeValue = barCode
d.listeners[d.protocolCommonConfig.Port].status = true
d.listeners[d.protocolCommonConfig.Port].reportTimes = 2 //one for devicetwin,and another for third-part application
}
}
}()
}
Loading