psmb

package module
v0.8.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 6, 2016 License: MIT Imports: 8 Imported by: 4

README

psmb

Docker GoDoc Go Report Card codecov

Proactive service library for modbusd


Continuous Integration

I do continuous integration and deploy docker images after git push by self-hosted drone.io server, circleci service, codecov service and dockerhub service.

CI Server Target Status
Travis API Build Status
CircleCI x86 CircleCI
Drone armhf Build Status

Environment variables

Why environment variable? Refer to the 12 factors

  • CONF_PSMBTCP: config file path
  • EP_BACKEND: endpoint of remote service discovery server (optional)

Contracts (Interfaces)

  • IProactiveService: proactive service
  • IReaderTaskDataStore: read/poll task data store
  • IWriterTaskDataStore: write task data store
  • IHistoryDataStore: history data store
  • IFilterDataStore: filter data store
  • IConfig: config management

Golang package management

  • I adopted glide as package management system for this repository.

Worker Pool Model

Request from upstream

uml

Response from downstream

uml


Up and Running

Docker Compose
docker-compose build --pull
docker-compose up
Manually
Install libzmq (3.2.5)
wget https://github.com/zeromq/zeromq3-x/releases/download/v3.2.5/zeromq-3.2.5.tar.gz
tar xvzf zeromq-3.2.5.tar.gz
cd zeromq-3.2.5
./configure
make
sudo make install
sudo ldconfig
Build
# install glide
curl https://glide.sh/get | sh

# install dependencies
glide up

# build
cd tcp-srv
go build -o psmbtcp-srv

Deployment Diagram

uml


Unit tests

  • binary
  • types

Test cases

Binary
  • Bytes to 16-bit integer array tests
    • BytesToUInt16s in big endian order - (1/4)
    • BytesToUInt16s in little endian order - (2/4)
    • BytesToInt16s in big endian order - (3/4)
    • BytesToInt16s in little endian order - (4/4)
  • Bytes to 32-bit integer array tests
    • BytesToUInt32s in (ABCD) Big Endian order - (1/4)
    • BytesToUInt32s in (DCBA) Little Endian order - (2/4)
    • BytesToUInt32s in (BADC) Mid-Big Endian order - (3/4)
    • BytesToUInt32s in (CDAB) Mid-Little Endian order - (4/4)
    • BytesToInt32s in (ABCD) Big Endian order - (1/4)
    • BytesToInt32s in (DCBA) Little Endian order - (2/4)
    • BytesToInt32s in (BADC) Mid-Big Endian order - (3/4)
    • BytesToInt32s in (CDAB) Mid-Little Endian order - (4/4)
  • Bytes to 32-bit float array tests
    • BytesToFloat32s in (ABCD) Big Endian order - (1/4)
    • BytesToFloat32s in (DCBA) Little Endian order - (2/4)
    • BytesToFloat32s in (BADC) Mid-Big Endian order - (3/4)
    • BytesToFloat32s in (CDAB) Mid-Little Endian order - (4/4)
  • Bytes/registers utility tests
    • BitStringToUInt8s test
    • BitStringToUInt8s test - left comma
    • BitStringToUInt8s test - right comma
    • BitStringToUInt8s test - left, right comma
    • RegistersToBytes test
    • BytesToHexString test
    • DecimalStringToRegisters test
    • DecimalStringToRegisters test - left comma
    • DecimalStringToRegisters test - right comma
    • DecimalStringToRegisters test - left, right comma
    • HexStringToRegisters test
    • HexStringToRegisters test - wrong length
    • LinearScalingRegisters test
    • LinearScalingRegisters test - (0,0,0,0)
    • LinearScalingRegisters test - reverse
Types
Upstream structure test
  • One-off modbus tcp struct tests
    • mbtcp.once.read request test
    • mbtcp.once.read response test
  • get/set modbus tcp timeout struct tests
    • mbtcp.timeout.read request test
    • mbtcp.timeout.read response test
    • mbtcp.timeout.update request test
    • mbtcp.timeout.update response test
    • mbtcp.once.write request test
    • mbtcp.once.write response test
Downstream structure test
  • modbus tcp downstreamstruct tests
    • read request test
    • single read response test
    • multiple read response test
    • single write request test
    • multiple write request test
    • set timeout request test
    • get timeout response test

UML

uml


License

MIT

Documentation

Overview

Package psmb a proactive service library for modbus daemon.

Define high-level Contracts(interface) and data types.

By taka@cmwang.net

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrBitStringToUInt8s is the error of BitStringToUInt8s conversion.
	ErrBitStringToUInt8s = errors.New("Fail to convert bit string to uint8 array")

	// ErrDecimalStringToRegisters is the error of DecimalStringToRegisters conversion.
	ErrDecimalStringToRegisters = errors.New("Fail to convert decimal string to uint16/words array in big endian order")

	// ErrHexStringToRegisters is the error of HexStringToRegisters conversion.
	ErrHexStringToRegisters = errors.New("Fail to convert hexadecimal string to uint16/words array in big endian order")

	// ErrRegistersToBytes is the error of RegistersToBytes conversion.
	ErrRegistersToBytes = errors.New("Fail to convert registers/uint16 array to byte array in big endian order")

	// ErrBytesToFloat32s is the error of BytesToFloat32s conversion.
	ErrBytesToFloat32s = errors.New("Fail to convert byte array to float32 array in four endian orders")

	// ErrNotANumber is the error of LinearScalingRegisters conversion.
	ErrNotANumber = errors.New("Fail to scale the registers linearly")

	// ErrBytesToInt32s is the error of BytesToInt32s conversion.
	ErrBytesToInt32s = errors.New("Fail to convert byte array to UInt32 array in four endian orders")

	// ErrBytesToUInt32s is the error of BytesToUInt32s conversion.
	ErrBytesToUInt32s = errors.New("Fail to convert byte array to UInt32 array in four endian orders")

	// ErrBytesToInt16s is the error of BytesToInt16s conversion.
	ErrBytesToInt16s = errors.New("Fail to convert byte array to Int16 array in two endian orders")

	// ErrBytesToUInt16s is the error of BytesToUInt16s conversion.
	ErrBytesToUInt16s = errors.New("Fail to convert byte array to UInt16 array in two endian orders")

	// ErrInvalidLengthToConvert is the error of invalid length to convert
	ErrInvalidLengthToConvert = errors.New("Invalid length to convert")
)

Functions

func BitStringToUInt8s

func BitStringToUInt8s(bitString string) ([]uint8, error)

BitStringToUInt8s converts bits string to uint8 array.

source: function code 15

func BytesToFloat32s

func BytesToFloat32s(buf []byte, endian Endian) ([]float32, error)

BytesToFloat32s converts byte array to float32 array in four endian orders. i.e.,

BigEndian (0),
LittleEndian (1)
MidBigEndian (2)
MidLittleEndian (3)

func BytesToHexString

func BytesToHexString(bytes []byte) string

BytesToHexString converts bytes array to hexadecimal string.

example: 112C004F12345678

func BytesToInt16s

func BytesToInt16s(buf []byte, endian Endian) ([]int16, error)

BytesToInt16s converts byte array to Int16 array in two endian orders. i.e.,

BigEndian (0) or LittleEndian (1)

func BytesToInt32s

func BytesToInt32s(buf []byte, endian Endian) ([]int32, error)

BytesToInt32s converts byte array to Int32 array in four endian orders. i.e.,

BigEndian (0),
LittleEndian (1)
MidBigEndian (2)
MidLittleEndian (3)

func BytesToUInt16s

func BytesToUInt16s(buf []byte, endian Endian) ([]uint16, error)

BytesToUInt16s converts byte array to UInt16 array in two endian orders. i.e.,

BigEndian (0) or LittleEndian (1)

func BytesToUInt32s

func BytesToUInt32s(buf []byte, endian Endian) ([]uint32, error)

BytesToUInt32s converts byte array to UInt32 array in four endian orders. i.e.,

BigEndian (0),
LittleEndian (1)
MidBigEndian (2)
MidLittleEndian (3)

func DecimalStringToRegisters

func DecimalStringToRegisters(decString string) ([]uint16, error)

DecimalStringToRegisters converts decimal string to uint16/words array in big endian order.

limitation: leading space before comma is not allowed.
source: upstream.

func HexStringToRegisters

func HexStringToRegisters(hexString string) ([]uint16, error)

HexStringToRegisters converts hexadecimal string to uint16/words array in big endian order.

source: upstream.

func LinearScalingRegisters

func LinearScalingRegisters(data []uint16, domainLow, domainHigh, rangeLow, rangeHigh float64) ([]float32, error)

LinearScalingRegisters scales the registers linearly. Equation:

Let domainLow, domainHigh, rangeLow, rangeHigh as a, b, c, d accordingly.
Output = c + (d - c) * (input - a) / (b - a)

func RegistersToBytes

func RegistersToBytes(data []uint16) ([]byte, error)

RegistersToBytes converts registers/uint16 array to byte array in big endian order.

source: downstream.

Types

type DMbtcpReadReq

type DMbtcpReadReq struct {
	// Tid unique transaction id in `string` format
	Tid string `json:"tid"`
	// Cmd modbusd command type: https://github.com/taka-wang/modbusd#command-mapping-table
	Cmd int `json:"cmd"`
	// IP ip address or hostname of the modbus tcp slave
	IP string `json:"ip"`
	// Port port number of the modbus tcp slave
	Port string `json:"port"`
	// Slave device id of the modbus tcp slave
	Slave uint8 `json:"slave"`
	// Addr start address for read
	Addr uint16 `json:"addr"`
	// Len the length of registers or bits
	Len uint16 `json:"len"`
}

DMbtcpReadReq downstream modbus tcp read request

type DMbtcpRes

type DMbtcpRes struct {
	// Tid unique transaction id in string format
	Tid string `json:"tid"`
	// Status response status string
	Status string `json:"status"`
	// Data for 'read function code' only.
	Data []uint16 `json:"data,omitempty"`
}

DMbtcpRes downstream modbus tcp read/write response

type DMbtcpTimeout

type DMbtcpTimeout struct {
	// Tid unique transaction id in `string` format
	Tid string `json:"tid"`
	// Cmd modbusd command type: https://github.com/taka-wang/modbusd#command-mapping-table
	Cmd int `json:"cmd"`
	// Status for response only.
	Status string `json:"status,omitempty"`
	// Timeout set timeout request and get timeout response only.
	Timeout int64 `json:"timeout,omitempty"`
}

DMbtcpTimeout downstream modbus tcp set/get timeout request/response

type DMbtcpWriteReq

type DMbtcpWriteReq struct {
	// Tid unique transaction id in `string` format
	Tid string `json:"tid"`
	// Cmd modbusd command type: https://github.com/taka-wang/modbusd#command-mapping-table
	Cmd int `json:"cmd"`
	// IP ip address or hostname of the modbus tcp slave
	IP string `json:"ip"`
	// Port port number of the modbus tcp slave
	Port string `json:"port"`
	// Slave device id of the modbus tcp slave
	Slave uint8 `json:"slave"`
	// Addr start address for write
	Addr uint16 `json:"addr"`
	// Len omit for fc5, fc6
	Len uint16 `json:"len,omitempty"`
	// Data should be []uint16, uint16 (FC5, FC6)
	Data interface{} `json:"data"`
}

DMbtcpWriteReq downstream modbus tcp write single bit/register request

type Endian

type Endian int

Endian defines byte endianness

const (

	// AB 16-bit words may be represented in big-endian format
	AB Endian
	// BA 16-bit words may be represented in little-endian format
	BA
)

16-bits Endian

const (

	// ABCD 32-bit words may be represented in big-endian format
	ABCD Endian
	// DCBA 32-bit words may be represented in little-endian format
	DCBA
	// BADC 32-bit words may be represented in mid-big-endian format
	BADC
	// CDAB 32-bit words may be represented in mid-little-endian format
	CDAB
)

32-bits Endian

const (

	// BigEndian 32-bit words may be represented in ABCD format
	BigEndian Endian
	// LittleEndian 32-bit words may be represented in DCBA format
	LittleEndian
	// MidBigEndian 32-bit words may be represented in BADC format
	MidBigEndian
	// MidLittleEndian 32-bit words may be represented in CDAB format
	MidLittleEndian
)

32-bits Endian

type FilterType

type FilterType int

FilterType filter type

const (
	// Change change or not
	Change FilterType = iota
	// GreaterEqual greater than or equal
	GreaterEqual
	// Greater greater than
	Greater
	// Equal equal
	Equal
	// Less less than
	Less
	// LessEqual less than or equal
	LessEqual
	// InsideRange inside range
	InsideRange
	// InsideIncRange inside range (include)
	InsideIncRange
	// OutsideRange outside range
	OutsideRange
	// OutsideIncRange outside range (include)
	OutsideIncRange
)

Filter value type

type HistoryData

type HistoryData struct {
	Ts   int64       `json:"ts,omitempty"`
	Data interface{} `json:"data,omitempty"` // universal data container
}

HistoryData history data

type IConfig

type IConfig interface {
	// contains filtered or unexported methods
}

IConfig config interface

type IFilterDataStore

type IFilterDataStore interface {
	// Add add request to filter map
	Add(name string, req interface{}) error
	// Get get request from filter map
	Get(name string) (interface{}, bool)
	// GetAll get all request from filter map
	GetAll() interface{}
	// Delete delete request from filter map
	Delete(name string)
	// DeleteAll delete all requests from filter map
	DeleteAll()
	// UpdateToggle update filter request enabled flag
	UpdateToggle(name string, toggle bool) error
	// UpdateAllToggles update all filter requests enabled flag
	UpdateAllToggles(toggle bool)
}

IFilterDataStore filter interface

type IHistoryDataStore

type IHistoryDataStore interface {
	// Add add history
	Add(name string, data interface{}) error
	// Get get history within range
	Get(name string, limit int) (map[string]string, error)
	// GetAll get all history
	GetAll(name string) (map[string]string, error)
	// GetLatest get latest history
	GetLatest(name string) (string, error)
}

IHistoryDataStore history interface

type IProactiveService

type IProactiveService interface {
	// Start enable proactive service
	Start()
	// Stop disable proactive service
	Stop()
	// ParseRequest parse requests from IT
	ParseRequest(msg []string) (interface{}, error)
	// HandleRequest handle requests from IT
	HandleRequest(cmd string, r interface{}) error
	// ParseResponse parse responses from OT
	ParseResponse(msg []string) (interface{}, error)
	// HandleResponse handle responses from OT
	HandleResponse(cmd string, r interface{}) error
}

IProactiveService proactive service contracts, all services should implement the following methods.

type IReaderTaskDataStore

type IReaderTaskDataStore interface {
	// Add add request to read/poll task map
	Add(name, tid, cmd string, req interface{}) error

	// GetTaskByID get request via TID from read/poll task map
	GetTaskByID(tid string) (interface{}, bool)

	// GetTaskByName get request via poll name from read/poll task map
	GetTaskByName(name string) (interface{}, bool)

	// GetAll get all requests from read/poll task map
	//	ex: mbtcp: []MbtcpPollStatus
	GetAll() interface{}

	// DeleteAll remove all requests from read/poll task map
	DeleteAll()

	// DeleteTaskByID remove request from via TID from read/poll task map
	DeleteTaskByID(tid string)

	// DeleteTaskByName remove request via poll name from read/poll task map
	DeleteTaskByName(name string)

	// UpdateIntervalByName update poll request interval
	UpdateIntervalByName(name string, interval uint64) error

	// UpdateToggleByName update poll request enabled flag
	UpdateToggleByName(name string, toggle bool) error

	// UpdateAllToggles update all poll requests enabled flag
	UpdateAllToggles(toggle bool)
}

IReaderTaskDataStore read task interface

type IWriterTaskDataStore

type IWriterTaskDataStore interface {
	// Add add request to write task map,
	// params: TID, CMD strings.
	Add(tid, cmd string)

	// Get get request from write task map,
	// params: TID string,
	// return: cmd string, exist flag.
	Get(tid string) (string, bool)

	// Delete remove request from write task map
	// params: TID string.
	Delete(tid string)
}

IWriterTaskDataStore write task interface

(Tid, Command) map

type JSONableByteSlice

type JSONableByteSlice []byte

JSONableByteSlice jsonable uint8 array

func (JSONableByteSlice) MarshalJSON

func (u JSONableByteSlice) MarshalJSON() ([]byte, error)

MarshalJSON implements the Marshaler interface on JSONableByteSlice (i.e., uint8/byte array). Ref: http://stackoverflow.com/questions/14177862/how-to-jsonize-a-uint8-slice-in-go

type MbtcpFilterOpReq

type MbtcpFilterOpReq struct {
	Tid     int64  `json:"tid"`
	From    string `json:"from,omitempty"`
	Name    string `json:"name,omitempty"`
	Enabled bool   `json:"enabled,omitempty"`
}

MbtcpFilterOpReq generic modbus tcp filter operation request

type MbtcpFilterStatus

type MbtcpFilterStatus struct {
	Tid     int64      `json:"tid"`
	From    string     `json:"from,omitempty"`
	Name    string     `json:"name"`
	Enabled bool       `json:"enabled"`
	Type    FilterType `json:"type,omitempty"`
	Arg     []float32  `json:"arg,omitempty"`
	Status  string     `json:"status,omitempty"`
}

MbtcpFilterStatus filter status

type MbtcpFiltersStatus

type MbtcpFiltersStatus struct {
	Tid     int64               `json:"tid"`
	From    string              `json:"from,omitempty"`
	Status  string              `json:"status,omitempty"`
	Filters []MbtcpFilterStatus `json:"filters"`
}

MbtcpFiltersStatus requests status

type MbtcpHistoryData

type MbtcpHistoryData struct {
	Tid    int64       `json:"tid"`
	Name   string      `json:"name"`
	Status string      `json:"status"`
	Data   interface{} `json:"history,omitempty"` // universal data container
}

MbtcpHistoryData history data

type MbtcpPollData

type MbtcpPollData struct {
	TimeStamp int64        `json:"ts"`
	Name      string       `json:"name"`
	Status    string       `json:"status"`
	Type      RegValueType `json:"type,omitempty"`
	// Bytes FC3, FC4 and Type 2~8 only
	Bytes JSONableByteSlice `json:"bytes,omitempty"`
	Data  interface{}       `json:"data,omitempty"` // universal data container
}

MbtcpPollData read coil/register response (1.1). `Data interface` supports:

[]uint16, []int16, []uint32, []int32, []float32, string

type MbtcpPollOpReq

type MbtcpPollOpReq struct {
	Tid      int64  `json:"tid"`
	From     string `json:"from,omitempty"`
	Name     string `json:"name,omitempty"`
	Interval uint64 `json:"interval,omitempty"`
	Enabled  bool   `json:"enabled,omitempty"`
}

MbtcpPollOpReq generic modbus tcp poll operation request

type MbtcpPollStatus

type MbtcpPollStatus struct {
	Tid      int64        `json:"tid"`
	From     string       `json:"from,omitempty"`
	Name     string       `json:"name"`
	Interval uint64       `json:"interval"`
	Enabled  bool         `json:"enabled"`
	FC       int          `json:"fc"`
	IP       string       `json:"ip"`
	Port     string       `json:"port,omitempty"`
	Slave    uint8        `json:"slave"`
	Addr     uint16       `json:"addr"`
	Status   string       `json:"status,omitempty"` // 2.3.2 response only
	Len      uint16       `json:"len,omitempty"`
	Type     RegValueType `json:"type,omitempty"`
	Order    Endian       `json:"order,omitempty"`
	Range    *ScaleRange  `json:"range,omitempty"` // point to struct can be omitted in json encode
}

MbtcpPollStatus polling coil/register request;

type MbtcpPollsStatus

type MbtcpPollsStatus struct {
	Tid    int64             `json:"tid"`
	From   string            `json:"from,omitempty"`
	Status string            `json:"status,omitempty"`
	Polls  []MbtcpPollStatus `json:"polls"`
}

MbtcpPollsStatus requests status

type MbtcpReadReq

type MbtcpReadReq struct {
	Tid   int64        `json:"tid"`
	From  string       `json:"from,omitempty"`
	FC    int          `json:"fc"`
	IP    string       `json:"ip"`
	Port  string       `json:"port,omitempty"`
	Slave uint8        `json:"slave"`
	Addr  uint16       `json:"addr"`
	Len   uint16       `json:"len,omitempty"`
	Type  RegValueType `json:"type,omitempty"`
	Order Endian       `json:"order,omitempty"`
	Range *ScaleRange  `json:"range,omitempty"` // point to struct can be omitted in json encode
}

MbtcpReadReq read coil/register request (1.1). Scale range field example:

Range: &ScaleRange{1,2,3,4},

type MbtcpReadRes

type MbtcpReadRes struct {
	Tid    int64        `json:"tid"`
	Status string       `json:"status"`
	Type   RegValueType `json:"type,omitempty"`
	// Bytes FC3, FC4 and Type 2~8 only
	Bytes JSONableByteSlice `json:"bytes,omitempty"`
	Data  interface{}       `json:"data,omitempty"` // universal data container
}

MbtcpReadRes read coil/register response (1.1). `Data interface` supports:

[]uint16, []int16, []uint32, []int32, []float32, string

type MbtcpSimpleRes

type MbtcpSimpleRes struct {
	Tid    int64  `json:"tid"`
	Status string `json:"status"`
}

MbtcpSimpleRes generic modbus tcp response

type MbtcpTimeoutReq

type MbtcpTimeoutReq struct {
	Tid  int64  `json:"tid"`
	From string `json:"from,omitempty"`
	Data int64  `json:"timeout,omitempty"`
}

MbtcpTimeoutReq set/get TCP connection timeout request (1.3, 1.4)

type MbtcpTimeoutRes

type MbtcpTimeoutRes struct {
	Tid    int64  `json:"tid"`
	Status string `json:"status"`
	Data   int64  `json:"timeout,omitempty"`
}

MbtcpTimeoutRes set/get TCP connection timeout response (1.3, 1.4)

type MbtcpWriteReq

type MbtcpWriteReq struct {
	Tid   int64       `json:"tid"`
	From  string      `json:"from,omitempty"`
	FC    int         `json:"fc"`
	IP    string      `json:"ip"`
	Port  string      `json:"port,omitempty"`
	Slave uint8       `json:"slave"`
	Addr  uint16      `json:"addr"`
	Len   uint16      `json:"len,omitempty"`
	Hex   bool        `json:"hex,omitempty"`
	Data  interface{} `json:"data"`
}

MbtcpWriteReq write coil/register request

type ReaderTask

type ReaderTask struct {
	// Name task name
	Name string
	// Cmd zmq frame 1
	Cmd string
	// Req request structure
	Req interface{}
}

ReaderTask read/poll task request

type RegValueType

type RegValueType int

RegValueType return value type defines how to inteprete registers, i.e.,

for modbus read function codes only
const (

	// RegisterArray register array, ex: [12345, 23456, 5678]
	RegisterArray RegValueType
	// HexString hexadecimal string, ex: "112C004F12345678"
	HexString
	// Scale linearly scale
	Scale
	// UInt16 uint16 array
	UInt16
	// Int16 int16 array
	Int16
	// UInt32 uint32 array
	UInt32
	// Int32 int32 array
	Int32
	// Float32 float32 array
	Float32
)

Register value type for read function

type ScaleRange

type ScaleRange struct {
	DomainLow  float64 `json:"a"`
	DomainHigh float64 `json:"b"`
	RangeLow   float64 `json:"c"`
	RangeHigh  float64 `json:"d"`
}

ScaleRange defines scale range

Directories

Path Synopsis
Package filter an in-memory data store for filter.
Package filter an in-memory data store for filter.
Package reader an in-memory data store for reader.
Package reader an in-memory data store for reader.
Package writer an in-memory data store for writer.
Package writer an in-memory data store for writer.
Package history an mongodb-based data store for history.
Package history an mongodb-based data store for history.
Package conf a multiconfig-based config By taka@cmwang.net
Package conf a multiconfig-based config By taka@cmwang.net
Package filter an redis-based data store for filter.
Package filter an redis-based data store for filter.
Package history an redis-based data store for history.
Package history an redis-based data store for history.
Package writer an redis-based data store for writer.
Package writer an redis-based data store for writer.
Package tcp provide proactive service library for modbus `TCP` .
Package tcp provide proactive service library for modbus `TCP` .
Package conf a viper-based config By taka@cmwang.net
Package conf a viper-based config By taka@cmwang.net

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL