canopen

package module
v1.1.1 Latest Latest
Warning

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

Go to latest
Published: Dec 31, 2023 License: GPL-3.0 Imports: 21 Imported by: 0

README

��# canopen

canopen is an implementation of the CANopen protocol (CiA 301) written in pure golang. It aims to be simple and efficient. This package can be used for master usage but also supports creating regular CANopen nodes.

Features

All the main components of CiA 301 are supported, these include :

  • SDO server/client
  • NMT master/slave
  • HB producer/consumer
  • TPDO/RPDO
  • EMERGENCY producer/consumer
  • SYNC producer/consumer
  • TIME

Partial support also exists for CiA 309, specifically :

  • HTTP gateway

go-canopen does not require the use of an external tool to generate some source code from an EDS file. EDS files can be loaded dynamically from disk to create local nodes with default supported objects.

Supported CAN transceivers

Currently this package only supports socketcan using : brutella/can However it can easily extended by creating your own driver. The following interface needs to be implemented

type Bus interface {
	Connect(...any) error                   // Connect to the actual bus
	Disconnect() error                      // Disconnect from bus
	Send(frame Frame) error                 // Send a frame on the bus
	Subscribe(callback FrameListener) error // Subscribe to all can frames
}

Feel free to contribute to add specific drivers, we will find a way to integrate them in this repo. This repo contains two implementation examples : socketcan.go, and virtual.go used for testing.

Usage

Examples can be found in /cmd

Basic setup example :

	network := canopen.NewNetwork(nil)
	e := network.Connect("socketcan", "can0", 500000)
	if e != nil {
		panic(e)
	}
	defer network.Disconnect()

	// Load a remote node OD to be able to read values from strings
	e = network.AddNode(0x10, "../../testdata/base.eds")
	if e != nil {
		panic(e)
	}

	network.Read(0x10, "INTEGER16 value", "")

Work ongoing

  • Improve documentation & examples
  • More testing
  • Adding support for kvaser (canlib)
  • Reduce boilerplate as much as possible
  • Improve API around "master" behaviour

Testing

Testing is done :

  • With unit tests of golang code (coverage is pretty low)
  • Help of an external python package (good coverage)

Tests are done with virtualcan server, which can be used easily with github actions. More tests are always welcome if you believe that some part of the spec is not properly tested.

For running tests, install the required packages pip install -r ./requirements.txt Run the tests with : pytest -v

Logs

The application uses the log package logrus Logs can be adjusted with different log levels :

import log "github.com/sirupsen/logrus"

log.SetLevel(log.DebugLevel)
// log.SetLevel(log.WarnLevel)

Credits

This work is heavily based on the C implementation by Janez ([https://github.com/CANopenNode/CANopenNode]) and also inspired by the python implementation by Christian Sandberg ([https://github.com/christiansandberg/canopen])

Documentation

Overview

CiA 309-5 implementation

Index

Constants

View Source
const (
	CAN_ERRTX_WARNING    = 0x0001 /**< 0x0001, CAN transmitter warning */
	CAN_ERRTX_PASSIVE    = 0x0002 /**< 0x0002, CAN transmitter passive */
	CAN_ERRTX_BUS_OFF    = 0x0004 /**< 0x0004, CAN transmitter bus off */
	CAN_ERRTX_OVERFLOW   = 0x0008 /**< 0x0008, CAN transmitter overflow */
	CAN_ERRTX_PDO_LATE   = 0x0080 /**< 0x0080, TPDO is outside sync window */
	CAN_ERRRX_WARNING    = 0x0100 /**< 0x0100, CAN receiver warning */
	CAN_ERRRX_PASSIVE    = 0x0200 /**< 0x0200, CAN receiver passive */
	CAN_ERRRX_OVERFLOW   = 0x0800 /**< 0x0800, CAN receiver overflow */
	CAN_ERR_WARN_PASSIVE = 0x0303 /**< 0x0303, combination */
)

CAN bus errors

View Source
const (
	CO_ERR_REG_GENERIC_ERR   = 0x01 /**< bit 0, generic error */
	CO_ERR_REG_CURRENT       = 0x02 /**< bit 1, current */
	CO_ERR_REG_VOLTAGE       = 0x04 /**< bit 2, voltage */
	CO_ERR_REG_TEMPERATURE   = 0x08 /**< bit 3, temperature */
	CO_ERR_REG_COMMUNICATION = 0x10 /**< bit 4, communication error */
	CO_ERR_REG_DEV_PROFILE   = 0x20 /**< bit 5, device profile specific */
	CO_ERR_REG_RESERVED      = 0x40 /**< bit 6, reserved (always 0) */
	CO_ERR_REG_MANUFACTURER  = 0x80 /**< bit 7, manufacturer specific */
)

Error register values

View Source
const (
	CO_EMC_NO_ERROR          = 0x0000
	CO_EMC_GENERIC           = 0x1000
	CO_EMC_CURRENT           = 0x2000
	CO_EMC_CURRENT_INPUT     = 0x2100
	CO_EMC_CURRENT_INSIDE    = 0x2200
	CO_EMC_CURRENT_OUTPUT    = 0x2300
	CO_EMC_VOLTAGE           = 0x3000
	CO_EMC_VOLTAGE_MAINS     = 0x3100
	CO_EMC_VOLTAGE_INSIDE    = 0x3200
	CO_EMC_VOLTAGE_OUTPUT    = 0x3300
	CO_EMC_TEMPERATURE       = 0x4000
	CO_EMC_TEMP_AMBIENT      = 0x4100
	CO_EMC_TEMP_DEVICE       = 0x4200
	CO_EMC_HARDWARE          = 0x5000
	CO_EMC_SOFTWARE_DEVICE   = 0x6000
	CO_EMC_SOFTWARE_INTERNAL = 0x6100
	CO_EMC_SOFTWARE_USER     = 0x6200
	CO_EMC_DATA_SET          = 0x6300
	CO_EMC_ADDITIONAL_MODUL  = 0x7000
	CO_EMC_MONITORING        = 0x8000
	CO_EMC_COMMUNICATION     = 0x8100
	CO_EMC_CAN_OVERRUN       = 0x8110
	CO_EMC_CAN_PASSIVE       = 0x8120
	CO_EMC_HEARTBEAT         = 0x8130
	CO_EMC_BUS_OFF_RECOVERED = 0x8140
	CO_EMC_CAN_ID_COLLISION  = 0x8150
	CO_EMC_PROTOCOL_ERROR    = 0x8200
	CO_EMC_PDO_LENGTH        = 0x8210
	CO_EMC_PDO_LENGTH_EXC    = 0x8220
	CO_EMC_DAM_MPDO          = 0x8230
	CO_EMC_SYNC_DATA_LENGTH  = 0x8240
	CO_EMC_RPDO_TIMEOUT      = 0x8250
	CO_EMC_EXTERNAL_ERROR    = 0x9000
	CO_EMC_ADDITIONAL_FUNC   = 0xF000
	CO_EMC_DEVICE_SPECIFIC   = 0xFF00
	CO_EMC401_OUT_CUR_HI     = 0x2310
	CO_EMC401_OUT_SHORTED    = 0x2320
	CO_EMC401_OUT_LOAD_DUMP  = 0x2330
	CO_EMC401_IN_VOLT_HI     = 0x3110
	CO_EMC401_IN_VOLT_LOW    = 0x3120
	CO_EMC401_INTERN_VOLT_HI = 0x3210
	CO_EMC401_INTERN_VOLT_LO = 0x3220
	CO_EMC401_OUT_VOLT_HIGH  = 0x3310
	CO_EMC401_OUT_VOLT_LOW   = 0x3320
)

Error codes

View Source
const (
	CO_EM_NO_ERROR                  = 0x00
	CO_EM_CAN_BUS_WARNING           = 0x01
	CO_EM_RXMSG_WRONG_LENGTH        = 0x02
	CO_EM_RXMSG_OVERFLOW            = 0x03
	CO_EM_RPDO_WRONG_LENGTH         = 0x04
	CO_EM_RPDO_OVERFLOW             = 0x05
	CO_EM_CAN_RX_BUS_PASSIVE        = 0x06
	CO_EM_CAN_TX_BUS_PASSIVE        = 0x07
	CO_EM_NMT_WRONG_COMMAND         = 0x08
	CO_EM_TIME_TIMEOUT              = 0x09
	CO_EM_0A_unused                 = 0x0A
	CO_EM_0B_unused                 = 0x0B
	CO_EM_0C_unused                 = 0x0C
	CO_EM_0D_unused                 = 0x0D
	CO_EM_0E_unused                 = 0x0E
	CO_EM_0F_unused                 = 0x0F
	CO_EM_10_unused                 = 0x10
	CO_EM_11_unused                 = 0x11
	CO_EM_CAN_TX_BUS_OFF            = 0x12
	CO_EM_CAN_RXB_OVERFLOW          = 0x13
	CO_EM_CAN_TX_OVERFLOW           = 0x14
	CO_EM_TPDO_OUTSIDE_WINDOW       = 0x15
	CO_EM_16_unused                 = 0x16
	CO_EM_RPDO_TIME_OUT             = 0x17
	CO_EM_SYNC_TIME_OUT             = 0x18
	CO_EM_SYNC_LENGTH               = 0x19
	CO_EM_PDO_WRONG_MAPPING         = 0x1A
	CO_EM_HEARTBEAT_CONSUMER        = 0x1B
	CO_EM_HB_CONSUMER_REMOTE_RESET  = 0x1C
	CO_EM_1D_unused                 = 0x1D
	CO_EM_1E_unused                 = 0x1E
	CO_EM_1F_unused                 = 0x1F
	CO_EM_EMERGENCY_BUFFER_FULL     = 0x20
	CO_EM_21_unused                 = 0x21
	CO_EM_MICROCONTROLLER_RESET     = 0x22
	CO_EM_23_unused                 = 0x23
	CO_EM_24_unused                 = 0x24
	CO_EM_25_unused                 = 0x25
	CO_EM_26_unused                 = 0x26
	CO_EM_NON_VOLATILE_AUTO_SAVE    = 0x27
	CO_EM_WRONG_ERROR_REPORT        = 0x28
	CO_EM_ISR_TIMER_OVERFLOW        = 0x29
	CO_EM_MEMORY_ALLOCATION_ERROR   = 0x2A
	CO_EM_GENERIC_ERROR             = 0x2B
	CO_EM_GENERIC_SOFTWARE_ERROR    = 0x2C
	CO_EM_INCONSISTENT_OBJECT_DICT  = 0x2D
	CO_EM_CALCULATION_OF_PARAMETERS = 0x2E
	CO_EM_NON_VOLATILE_MEMORY       = 0x2F
	CO_EM_MANUFACTURER_START        = 0x30
	CO_EM_MANUFACTURER_END          = CO_CONFIG_EM_ERR_STATUS_BITS_COUNT - 1
)

Error status bits

View Source
const (
	HB_UNCONFIGURED       = 0x00 /**< Consumer entry inactive */
	HB_UNKNOWN            = 0x01 /**< Consumer enabled, but no heartbeat received yet */
	HB_ACTIVE             = 0x02 /**< Heartbeat received within set time */
	HB_TIMEOUT            = 0x03 /**< No heatbeat received for set time */
	NMT_UNKNOWN     int16 = -1
)
View Source
const (
	NMT_ERR_REG_MASK            uint16 = 0x00FF
	NMT_STARTUP_TO_OPERATIONAL  uint16 = 0x0100
	NMT_ERR_ON_BUSOFF_HB        uint16 = 0x1000
	NMT_ERR_ON_ERR_REG          uint16 = 0x2000
	NMT_ERR_TO_STOPPED          uint16 = 0x4000
	NMT_ERR_FREE_TO_OPERATIONAL uint16 = 0x8000
)
View Source
const (
	RESET_NOT  uint8 = 0
	RESET_COMM uint8 = 1
	RESET_APP  uint8 = 2
	RESET_QUIT uint8 = 3
)
View Source
const (
	NMT_INITIALIZING    uint8 = 0
	NMT_PRE_OPERATIONAL uint8 = 127
	NMT_OPERATIONAL     uint8 = 5
	NMT_STOPPED         uint8 = 4
)
View Source
const (
	NMT_SERVICE_ID       uint16 = 0
	EMERGENCY_SERVICE_ID uint16 = 0x80
	HEARTBEAT_SERVICE_ID uint16 = 0x700
	SDO_SERVER_ID        uint16 = 0x580
	SDO_CLIENT_ID        uint16 = 0x600
)
View Source
const (
	NODE_INIT     uint8 = 0
	NODE_RUNNING  uint8 = 1
	NODE_RESETING uint8 = 2
	NODE_EXIT     uint8 = 3
)
View Source
const (
	ATTRIBUTE_SDO_R  uint8 = 0x01 // SDO server may read from the variable
	ATTRIBUTE_SDO_W  uint8 = 0x02 //SDO server may write to the variable
	ATTRIBUTE_SDO_RW uint8 = 0x03 // SDO server may read from or write to the variable
	ATTRIBUTE_TPDO   uint8 = 0x04 //Variable is mappable into TPDO (can be read)
	ATTRIBUTE_RPDO   uint8 = 0x08 //Variable is mappable into RPDO (can be written)
	ATTRIBUTE_TRPDO  uint8 = 0x0C //Variable is mappable into TPDO or RPDO
	ATTRIBUTE_TSRDO  uint8 = 0x10 //Variable is mappable into transmitting SRDO
	ATTRIBUTE_RSRDO  uint8 = 0x20 //Variable is mappable into receiving SRDO
	ATTRIBUTE_TRSRDO uint8 = 0x30 //Variable is mappable into tx or rx SRDO
	ATTRIBUTE_MB     uint8 = 0x40 //Variable is multi-byte ((u)int16_t to (u)int64_t)
	ATTRIBUTE_STR    uint8 = 0x80 //Shorter value, than specified variable size, may be

)

Object dictionary object attribute

View Source
const (
	OBJ_DOMAIN byte = 2
	OBJ_VAR    byte = 7
	OBJ_ARR    byte = 8
	OBJ_RECORD byte = 9
)

CANopen supported object types

View Source
const (
	BOOLEAN        uint8 = 0x01
	INTEGER8       uint8 = 0x02
	INTEGER16      uint8 = 0x03
	INTEGER32      uint8 = 0x04
	UNSIGNED8      uint8 = 0x05
	UNSIGNED16     uint8 = 0x06
	UNSIGNED32     uint8 = 0x07
	REAL32         uint8 = 0x08
	VISIBLE_STRING uint8 = 0x09
	OCTET_STRING   uint8 = 0x0A
	UNICODE_STRING uint8 = 0x0B
	DOMAIN         uint8 = 0x0F
	REAL64         uint8 = 0x11
	INTEGER64      uint8 = 0x15
	UNSIGNED64     uint8 = 0x1B
)

CANopen supported datatypes

View Source
const (
	ODT_VAR       byte = 0x01
	ODT_ARR       byte = 0x02
	ODT_REC       byte = 0x03
	ODT_TYPE_MASK byte = 0x0F
)

Actual object type used in OD Specifically, OBJ_DOMAIN is considered as an ODT_VAR

View Source
const (
	MAX_PDO_LENGTH     uint8 = 8
	MAX_MAPPED_ENTRIES uint8 = 8
	OD_FLAGS_PDO_SIZE  uint8 = 32
	RPDO_BUFFER_COUNT  uint8 = 2
)
View Source
const (
	TRANSMISSION_TYPE_SYNC_ACYCLIC  = 0    // synchronous (acyclic)
	TRANSMISSION_TYPE_SYNC_1        = 1    // synchronous (cyclic every sync)
	TRANSMISSION_TYPE_SYNC_240      = 0xF0 // synchronous (cyclic every 240-th sync)
	TRANSMISSION_TYPE_SYNC_EVENT_LO = 0xFE // event-driven, lower value (manufacturer specific)
	TRANSMISSION_TYPE_SYNC_EVENT_HI = 0xFF // event-driven, higher value (device profile and application profile specific)
)
View Source
const (
	CO_RPDO_RX_ACK_NO_ERROR = 0  /* No error */
	CO_RPDO_RX_ACK_ERROR    = 1  /* Error is acknowledged */
	CO_RPDO_RX_ACK          = 10 /* Auxiliary value */
	CO_RPDO_RX_OK           = 11 /* Correct RPDO received, not acknowledged */
	CO_RPDO_RX_SHORT        = 12 /* Too short RPDO received, not acknowledged */
	CO_RPDO_RX_LONG         = 13 /* Too long RPDO received, not acknowledged */
)
View Source
const (
	SDO_WAITING_LOCAL_TRANSFER     uint8 = 6 // Waiting in client local transfer.
	SDO_UPLOAD_DATA_FULL           uint8 = 5 // Data buffer is full.SDO client: data must be read before next upload cycle begins.
	SDO_TRANSMIT_BUFFER_FULL       uint8 = 4 // CAN transmit buffer is full. Waiting.
	SDO_BLOCK_DOWNLOAD_IN_PROGRESS uint8 = 3 // Block download is in progress. Sending train of messages.
	SDO_BLOCK_UPLOAD_IN_PROGRESS   uint8 = 2 // Block upload is in progress. Receiving train of messages.SDO client: Data must not be read in this state.
	SDO_WAITING_RESPONSE           uint8 = 1 // Waiting server or client response.
	SDO_SUCCESS                    uint8 = 0 // Success, end of communication. SDO client: uploaded data must be read.

)
View Source
const (
	CO_SYNC_NONE          uint8 = 0 /** No SYNC event in last cycle */
	CO_SYNC_RX_TX         uint8 = 1 /** SYNC message was received or transmitted in last cycle */
	CO_SYNC_PASSED_WINDOW uint8 = 2 /** Time has just passed SYNC window (OD_1007) in last cycle */
)
View Source
const API_VERSION = "1.0"
View Source
const BASE_RPDO_COMMUNICATION_INDEX = uint16(0x1400)
View Source
const BASE_RPDO_MAPPING_INDEX = uint16(0x1600)
View Source
const BASE_TPDO_COMMUNICATION_INDEX = uint16(0x1800)
View Source
const BASE_TPDO_MAPPING_INDEX = uint16(0x1A00)
View Source
const CAN_EFF_FLAG uint32 = 0x80000000
View Source
const CAN_RTR_FLAG uint32 = 0x40000000
View Source
const CAN_SFF_MASK uint32 = 0x000007FF
View Source
const CO_CONFIG_EM_ERR_STATUS_BITS_COUNT = 80
View Source
const CO_CONFIG_SDO_CLI_PST = 21
View Source
const DEFAULT_SDO_CLIENT_TIMEOUT_MS = 1000
View Source
const MAX_SEQUENCE_NB = 2<<31 - 1
View Source
const PDO_COMMAND_URI_PATTERN = `(r|read|w|write)/(p|pdo)/(0x[0-9a-f]{1,3}|\d{1,4})`
View Source
const SDO_CLIENT_TIMEOUT = 1000
View Source
const SDO_CLI_BUFFER_SIZE = 1000
View Source
const SDO_COMMAND_URI_PATTERN = `(r|read|w|write)/(all|0x[0-9a-f]{1,4}|\d{1,5})/?(0x[0-9a-f]{1,2}|\d{1,3})?`
View Source
const SDO_SERVER_TIMEOUT = 1000
View Source
const URI_PATTERN = `/cia309-5/(\d+\.\d+)/(\d{1,10})/(0x[0-9a-f]{1,4}|\d{1,10}|default|none|all)/(0x[0-9a-f]{1,2}|\d{1,3}|default|none|all)/(.*)`

Variables

View Source
var (
	ErrIllegalArgument       = errors.New("error in function arguments")
	ErrOutOfMemory           = errors.New("memory allocation failed")
	ErrTimeout               = errors.New("function timeout")
	ErrIllegalBaudrate       = errors.New("illegal baudrate passed to function")
	ErrRxOverflow            = errors.New("previous message was not processed yet")
	ErrRxPdoOverflow         = errors.New("previous PDO was not processed yet")
	ErrRxMsgLength           = errors.New("wrong receive message length")
	ErrRxPdoLength           = errors.New("wrong receive PDO length")
	ErrTxOverflow            = errors.New("previous message is still waiting, buffer full")
	ErrTxPdoWindow           = errors.New("synchronous TPDO is outside window")
	ErrTxUnconfigured        = errors.New("transmit buffer was not configured properly")
	ErrOdParameters          = errors.New("error in Object Dictionary parameters")
	ErrDataCorrupt           = errors.New("stored data are corrupt")
	ErrCRC                   = errors.New("crc does not match")
	ErrTxBusy                = errors.New("sending rejected because driver is busy. Try again")
	ErrWrongNMTState         = errors.New("command can't be processed in the current state")
	ErrSyscall               = errors.New("syscall failed")
	ErrInvalidState          = errors.New("driver not ready")
	ErrNodeIdUnconfiguredLSS = errors.New("node-id is in LSS unconfigured state. If objects are handled properly, this may not be an error")
)
View Source
var (
	ErrGwRequestNotSupported         = &HTTPGatewayError{Code: 100}
	ErrGwSyntaxError                 = &HTTPGatewayError{Code: 101}
	ErrGwRequestNotProcessed         = &HTTPGatewayError{Code: 102}
	ErrGwTimeout                     = &HTTPGatewayError{Code: 103}
	ErrGwNoDefaultNetSet             = &HTTPGatewayError{Code: 104}
	ErrGwNoDefaultNodeSet            = &HTTPGatewayError{Code: 105}
	ErrGwUnsupportedNet              = &HTTPGatewayError{Code: 106}
	ErrGwUnsupportedNode             = &HTTPGatewayError{Code: 107}
	ErrGwCommandCancellationFailed   = &HTTPGatewayError{Code: 108}
	ErrGwEmergencyConsumerNotEnabled = &HTTPGatewayError{Code: 109}
	ErrGwWrongNMTState               = &HTTPGatewayError{Code: 204}
	ErrGwWrongPassword               = &HTTPGatewayError{Code: 300}
	ErrGwSuperUsersExceeded          = &HTTPGatewayError{Code: 301}
	ErrGwNodeAccessDenied            = &HTTPGatewayError{Code: 302}
	ErrGwNoSessionAvailable          = &HTTPGatewayError{Code: 303}
	ErrGwPDOAlreadyUsed              = &HTTPGatewayError{Code: 400}
	ErrGwPDOLengthExceeded           = &HTTPGatewayError{Code: 401}
	ErrGwLSSImplementationError      = &HTTPGatewayError{Code: 501}
	ErrGwLSSNodeIDNotSupported       = &HTTPGatewayError{Code: 502}
	ErrGwLSSBitRateNotSupported      = &HTTPGatewayError{Code: 503}
	ErrGwLSSParameterStoringFailed   = &HTTPGatewayError{Code: 504}
	ErrGwLSSCommandFailed            = &HTTPGatewayError{Code: 505}
	ErrGwRunningOutOfMemory          = &HTTPGatewayError{Code: 600}
	ErrGwCANInterfaceNotAvailable    = &HTTPGatewayError{Code: 601}
	ErrGwSizeLowerThanSDOBufferSize  = &HTTPGatewayError{Code: 602}
	ErrGwManufacturerSpecificError   = &HTTPGatewayError{Code: 900}
)
View Source
var ERROR_CODE_MAP = map[int]string{
	CO_EMC_NO_ERROR:          "Reset or No Error",
	CO_EMC_GENERIC:           "Generic Error",
	CO_EMC_CURRENT:           "Current",
	CO_EMC_CURRENT_INPUT:     "Current, device input side",
	CO_EMC_CURRENT_INSIDE:    "Current inside the device",
	CO_EMC_CURRENT_OUTPUT:    "Current, device output side",
	CO_EMC_VOLTAGE:           "Voltage",
	CO_EMC_VOLTAGE_MAINS:     "Mains Voltage",
	CO_EMC_VOLTAGE_INSIDE:    "Voltage inside the device",
	CO_EMC_VOLTAGE_OUTPUT:    "Output Voltage",
	CO_EMC_TEMPERATURE:       "Temperature",
	CO_EMC_TEMP_AMBIENT:      "Ambient Temperature",
	CO_EMC_TEMP_DEVICE:       "Device Temperature",
	CO_EMC_HARDWARE:          "Device Hardware",
	CO_EMC_SOFTWARE_DEVICE:   "Device Software",
	CO_EMC_SOFTWARE_INTERNAL: "Internal Software",
	CO_EMC_SOFTWARE_USER:     "User Software",
	CO_EMC_DATA_SET:          "Data Set",
	CO_EMC_ADDITIONAL_MODUL:  "Additional Modules",
	CO_EMC_MONITORING:        "Monitoring",
	CO_EMC_COMMUNICATION:     "Communication",
	CO_EMC_CAN_OVERRUN:       "CAN Overrun (Objects lost)",
	CO_EMC_CAN_PASSIVE:       "CAN in Error Passive Mode",
	CO_EMC_HEARTBEAT:         "Life Guard Error or Heartbeat Error",
	CO_EMC_BUS_OFF_RECOVERED: "Recovered from bus off",
	CO_EMC_CAN_ID_COLLISION:  "CAN-ID collision",
	CO_EMC_PROTOCOL_ERROR:    "Protocol Error",
	CO_EMC_PDO_LENGTH:        "PDO not processed due to length error",
	CO_EMC_PDO_LENGTH_EXC:    "PDO length exceeded",
	CO_EMC_DAM_MPDO:          "DAM MPDO not processed, destination object not available",
	CO_EMC_SYNC_DATA_LENGTH:  "Unexpected SYNC data length",
	CO_EMC_RPDO_TIMEOUT:      "RPDO timeout",
	CO_EMC_EXTERNAL_ERROR:    "External Error",
	CO_EMC_ADDITIONAL_FUNC:   "Additional Functions",
	CO_EMC_DEVICE_SPECIFIC:   "Device specific",
	CO_EMC401_OUT_CUR_HI:     "DS401, Current at outputs too high (overload)",
	CO_EMC401_OUT_SHORTED:    "DS401, Short circuit at outputs",
	CO_EMC401_OUT_LOAD_DUMP:  "DS401, Load dump at outputs",
	CO_EMC401_IN_VOLT_HI:     "DS401, Input voltage too high",
	CO_EMC401_IN_VOLT_LOW:    "DS401, Input voltage too low",
	CO_EMC401_INTERN_VOLT_HI: "DS401, Internal voltage too high",
	CO_EMC401_INTERN_VOLT_LO: "DS401, Internal voltage too low",
	CO_EMC401_OUT_VOLT_HIGH:  "DS401, Output voltage too high",
	CO_EMC401_OUT_VOLT_LOW:   "DS401, Output voltage too low",
}
View Source
var ERROR_GATEWAY_DESCRIPTION_MAP = map[int]string{
	100: "Request not supported",
	101: "Syntax error",
	102: "Request not processed due to internal state",
	103: "Time-out (where applicable)",
	104: "No default net set",
	105: "No default node set",
	106: "Unsupported net",
	107: "Unsupported node",
	108: "Command cancellation failed or ignored",
	109: "Emergency consumer not enabled",
	204: "Wrong NMT state",
	300: "Wrong password (User management)",
	301: "Number of super users exceeded (User management)",
	302: "Node access denied (User management)",
	303: "No session available (User management)",
	400: "PDO already used",
	401: "PDO length exceeded",
	501: "LSS implementation-/manufacturer-specific error",
	502: "LSS node-ID not supported",
	503: "LSS bit-rate not supported",
	504: "LSS parameter storing failed",
	505: "LSS command failed because of media error",
	600: "Running out of memory",
	601: "CAN interface currently not available",
	602: "Size to be set lower than minimum SDO buffer size",
	900: "Manufacturer-specific error",
}
View Source
var ERROR_STATUS_MAP = map[uint8]string{
	CO_EM_NO_ERROR:                  "Error Reset or No Error",
	CO_EM_CAN_BUS_WARNING:           "CAN bus warning limit reached",
	CO_EM_RXMSG_WRONG_LENGTH:        "Wrong data length of the received CAN message",
	CO_EM_RXMSG_OVERFLOW:            "Previous received CAN message wasn't processed yet",
	CO_EM_RPDO_WRONG_LENGTH:         "Wrong data length of received PDO",
	CO_EM_RPDO_OVERFLOW:             "Previous received PDO wasn't processed yet",
	CO_EM_CAN_RX_BUS_PASSIVE:        "CAN receive bus is passive",
	CO_EM_CAN_TX_BUS_PASSIVE:        "CAN transmit bus is passive",
	CO_EM_NMT_WRONG_COMMAND:         "Wrong NMT command received",
	CO_EM_TIME_TIMEOUT:              "TIME message timeout",
	CO_EM_0A_unused:                 "(unused)",
	CO_EM_0B_unused:                 "(unused)",
	CO_EM_0C_unused:                 "(unused)",
	CO_EM_0D_unused:                 "(unused)",
	CO_EM_0E_unused:                 "(unused)",
	CO_EM_0F_unused:                 "(unused)",
	CO_EM_10_unused:                 "(unused)",
	CO_EM_11_unused:                 "(unused)",
	CO_EM_CAN_TX_BUS_OFF:            "CAN transmit bus is off",
	CO_EM_CAN_RXB_OVERFLOW:          "CAN module receive buffer has overflowed",
	CO_EM_CAN_TX_OVERFLOW:           "CAN transmit buffer has overflowed",
	CO_EM_TPDO_OUTSIDE_WINDOW:       "TPDO is outside SYNC window",
	CO_EM_16_unused:                 "(unused)",
	CO_EM_RPDO_TIME_OUT:             "RPDO message timeout",
	CO_EM_SYNC_TIME_OUT:             "SYNC message timeout",
	CO_EM_SYNC_LENGTH:               "Unexpected SYNC data length",
	CO_EM_PDO_WRONG_MAPPING:         "Error with PDO mapping",
	CO_EM_HEARTBEAT_CONSUMER:        "Heartbeat consumer timeout",
	CO_EM_HB_CONSUMER_REMOTE_RESET:  "Heartbeat consumer detected remote node reset",
	CO_EM_1D_unused:                 "(unused)",
	CO_EM_1E_unused:                 "(unused)",
	CO_EM_1F_unused:                 "(unused)",
	CO_EM_EMERGENCY_BUFFER_FULL:     "Emergency buffer is full, Emergency message wasn't sent",
	CO_EM_21_unused:                 "(unused)",
	CO_EM_MICROCONTROLLER_RESET:     "Microcontroller has just started",
	CO_EM_23_unused:                 "(unused)",
	CO_EM_24_unused:                 "(unused)",
	CO_EM_25_unused:                 "(unused)",
	CO_EM_26_unused:                 "(unused)",
	CO_EM_NON_VOLATILE_AUTO_SAVE:    "Automatic store to non-volatile memory failed",
	CO_EM_WRONG_ERROR_REPORT:        "Wrong parameters to ErrorReport function",
	CO_EM_ISR_TIMER_OVERFLOW:        "Timer task has overflowed",
	CO_EM_MEMORY_ALLOCATION_ERROR:   "Unable to allocate memory for objects",
	CO_EM_GENERIC_ERROR:             "Generic error, test usage",
	CO_EM_GENERIC_SOFTWARE_ERROR:    "Software error",
	CO_EM_INCONSISTENT_OBJECT_DICT:  "Object dictionary does not match the software",
	CO_EM_CALCULATION_OF_PARAMETERS: "Error in calculation of device parameters",
	CO_EM_NON_VOLATILE_MEMORY:       "Error with access to non-volatile device memory",
}
View Source
var ErrSDOInvalidArguments = errors.New("error in arguments")
View Source
var HTTP_DATATYPE_MAP = map[string]uint8{
	"b":   BOOLEAN,
	"u8":  UNSIGNED8,
	"u16": UNSIGNED16,
	"u32": UNSIGNED32,
	"u64": UNSIGNED64,
	"i8":  INTEGER8,
	"i16": INTEGER16,
	"i32": INTEGER32,
	"i64": INTEGER64,
	"r32": REAL32,
	"r64": REAL64,
	"vs":  VISIBLE_STRING,
}
View Source
var NMT_COMMAND_MAP = map[NMTCommand]string{
	NMT_ENTER_OPERATIONAL:     "ENTER-OPERATIONAL",
	NMT_ENTER_STOPPED:         "ENTER-STOPPED",
	NMT_ENTER_PRE_OPERATIONAL: "ENTER-PREOPERATIONAL",
	NMT_RESET_NODE:            "RESET-NODE",
	NMT_RESET_COMMUNICATION:   "RESET-COMMUNICATION",
}
View Source
var NMT_STATE_MAP = map[uint8]string{
	NMT_INITIALIZING:    "INITIALIZING",
	NMT_PRE_OPERATIONAL: "PRE-OPERATIONAL",
	NMT_OPERATIONAL:     "OPERATIONAL",
	NMT_STOPPED:         "STOPPED",
}
View Source
var OBJ_NAME_MAP = map[byte]string{
	OBJ_DOMAIN: "DOMAIN  ",
	OBJ_VAR:    "VARIABLE",
	OBJ_ARR:    "ARRAY   ",
	OBJ_RECORD: "RECORD  ",
}
View Source
var SDO_ABORT_EXPLANATION_MAP = map[SDOAbortCode]string{
	SDO_ABORT_TOGGLE_BIT:         "Toggle bit not altered",
	SDO_ABORT_TIMEOUT:            "SDO protocol timed out",
	SDO_ABORT_CMD:                "Command specifier not valid or unknown",
	SDO_ABORT_BLOCK_SIZE:         "Invalid block size in block mode",
	SDO_ABORT_SEQ_NUM:            "Invalid sequence number in block mode",
	SDO_ABORT_CRC:                "CRC error (block mode only)",
	SDO_ABORT_OUT_OF_MEM:         "Out of memory",
	SDO_ABORT_UNSUPPORTED_ACCESS: "Unsupported access to an object",
	SDO_ABORT_WRITEONLY:          "Attempt to read a write only object",
	SDO_ABORT_READONLY:           "Attempt to write a read only object",
	SDO_ABORT_NOT_EXIST:          "Object does not exist in the object dictionary",
	SDO_ABORT_NO_MAP:             "Object cannot be mapped to the PDO",
	SDO_ABORT_MAP_LEN:            "Num and len of object to be mapped exceeds PDO len",
	SDO_ABORT_PRAM_INCOMPAT:      "General parameter incompatibility reasons",
	SDO_ABORT_DEVICE_INCOMPAT:    "General internal incompatibility in device",
	SDO_ABORT_HW:                 "Access failed due to hardware error",
	SDO_ABORT_TYPE_MISMATCH:      "Data type does not match, length does not match",
	SDO_ABORT_DATA_LONG:          "Data type does not match, length too high",
	SDO_ABORT_DATA_SHORT:         "Data type does not match, length too short",
	SDO_ABORT_SUB_UNKNOWN:        "Sub index does not exist",
	SDO_ABORT_INVALID_VALUE:      "Invalid value for parameter (download only)",
	SDO_ABORT_VALUE_HIGH:         "Value range of parameter written too high",
	SDO_ABORT_VALUE_LOW:          "Value range of parameter written too low",
	SDO_ABORT_MAX_LESS_MIN:       "Maximum value is less than minimum value.",
	SDO_ABORT_NO_RESOURCE:        "Resource not available: SDO connection",
	SDO_ABORT_GENERAL:            "General error",
	SDO_ABORT_DATA_TRANSF:        "Data cannot be transferred or stored to application",
	SDO_ABORT_DATA_LOC_CTRL:      "Data cannot be transferred because of local control",
	SDO_ABORT_DATA_DEV_STATE:     "Data cannot be tran. because of present device state",
	SDO_ABORT_DATA_OD:            "Object dict. not present or dynamic generation fails",
	SDO_ABORT_NO_DATA:            "No data available",
}

Functions

func ReadDummy

func ReadDummy(stream *Stream, data []byte, countRead *uint16) error

RPDOTPDO read method that fakes reading an OD variable

func ReadEntry1003

func ReadEntry1003(stream *Stream, data []byte, countRead *uint16) error

[EMERGENCY] read emergency history

func ReadEntry1014

func ReadEntry1014(stream *Stream, data []byte, countRead *uint16) error

[EMERGENCY] read emergency cob id

func ReadEntry14xxOr18xx

func ReadEntry14xxOr18xx(stream *Stream, data []byte, countRead *uint16) error

RPDOTPDO get communication parameter

func ReadEntryDefault

func ReadEntryDefault(stream *Stream, data []byte, countRead *uint16) error

This is the default "StreamReader" type for every OD entry Read value from original OD location and transfer it into a new byte slice

func ReadEntryDisabled

func ReadEntryDisabled(stream *Stream, data []byte, countRead *uint16) error

Read value from variable from Object Dictionary disabled

func ReadEntryFileObject

func ReadEntryFileObject(stream *Stream, data []byte, countRead *uint16) error

[SDO] Custom function for reading a file like object

func ReadEntryStatusBits

func ReadEntryStatusBits(stream *Stream, data []byte, countRead *uint16) error

func WriteDummy

func WriteDummy(stream *Stream, data []byte, countWritten *uint16) error

RPDOTPDO write method that fakes writing an OD variable

func WriteEntry1003

func WriteEntry1003(stream *Stream, data []byte, countWritten *uint16) error

[EMERGENCY] clear emergency history

func WriteEntry1005

func WriteEntry1005(stream *Stream, data []byte, countWritten *uint16) error

SYNC update cob id & if should be producer

func WriteEntry1006

func WriteEntry1006(stream *Stream, data []byte, countWritten *uint16) error

SYNC update communication cycle period

func WriteEntry1007

func WriteEntry1007(stream *Stream, data []byte, countWritten *uint16) error

SYNC update pdo synchronous window length

func WriteEntry1012

func WriteEntry1012(stream *Stream, data []byte, countWritten *uint16) error

TIME update cob id & if should be producer

func WriteEntry1014

func WriteEntry1014(stream *Stream, data []byte, countWritten *uint16) error

[EMERGENCY] update emergency producer cob id

func WriteEntry1015

func WriteEntry1015(stream *Stream, data []byte, countWritten *uint16) error

[EMERGENCY] update inhibite time

func WriteEntry1016

func WriteEntry1016(stream *Stream, data []byte, countWritten *uint16) error

[HB Consumer] update heartbeat consumer

func WriteEntry1017

func WriteEntry1017(stream *Stream, data []byte, countWritten *uint16) error

NMT update heartbeat period

func WriteEntry1019

func WriteEntry1019(stream *Stream, data []byte, countWritten *uint16) error

SYNC update synchronous counter overflow

func WriteEntry1201

func WriteEntry1201(stream *Stream, data []byte, countWritten *uint16) error

[SDO server] update server parameters

func WriteEntry1280

func WriteEntry1280(stream *Stream, data []byte, countWritten *uint16) error

[SDO Client] update parameters

func WriteEntry14xx

func WriteEntry14xx(stream *Stream, data []byte, countWritten *uint16) error

RPDO update communication parameter

func WriteEntry16xxOr1Axx

func WriteEntry16xxOr1Axx(stream *Stream, data []byte, countWritten *uint16) error

RPDOTPDO update mapping parameter

func WriteEntry18xx

func WriteEntry18xx(stream *Stream, data []byte, countWritten *uint16) error

TPDO update communication parameter

func WriteEntryDefault

func WriteEntryDefault(stream *Stream, data []byte, countWritten *uint16) error

This is the default "StreamWriter" type for every OD entry Write value to original OD location

func WriteEntryDisabled

func WriteEntryDisabled(stream *Stream, data []byte, countWritten *uint16) error

Write value to variable from Object Dictionary disabled

func WriteEntryFileObject

func WriteEntryFileObject(stream *Stream, data []byte, countWritten *uint16) error

[SDO] Custom function for writing a file like object

func WriteEntryStatusBits

func WriteEntryStatusBits(stream *Stream, data []byte, countWritten *uint16) error

Types

type BaseNode

type BaseNode struct {
	MainCallback func(args ...any)
	// contains filtered or unexported fields
}

func (*BaseNode) GetExit

func (node *BaseNode) GetExit() chan bool

func (*BaseNode) GetExitBackground

func (node *BaseNode) GetExitBackground() chan bool

func (*BaseNode) GetID

func (node *BaseNode) GetID() uint8

func (*BaseNode) GetOD

func (node *BaseNode) GetOD() *ObjectDictionary

func (*BaseNode) GetState

func (node *BaseNode) GetState() uint8

func (*BaseNode) SetExit

func (node *BaseNode) SetExit(exit bool)

func (*BaseNode) SetExitBackground

func (node *BaseNode) SetExitBackground(exit bool)

func (*BaseNode) SetState

func (node *BaseNode) SetState(newState uint8)

type Bus

type Bus interface {
	Connect(...any) error                   // Connect to the actual bus
	Disconnect() error                      // Disconnect from bus
	Send(frame Frame) error                 // Send a frame on the bus
	Subscribe(callback FrameListener) error // Subscribe to all can frames
}

A CAN Bus interface A custom implementation should implement all these methods

type BusManager

type BusManager struct {
	Bus Bus // Bus interface that can be adapted

	CANerrorstatus    uint16
	CANnormal         bool
	UseCANrxFilters   bool
	BufferInhibitFlag bool
	FirstCANtxMessage bool
	CANtxCount        uint32
	ErrOld            uint32
	// contains filtered or unexported fields
}

Bus manager is a wrapper around the CAN bus interface Used by the CANopen stack to control errors, callbacks for specific IDs, etc.

func NewBusManager

func NewBusManager(bus Bus) *BusManager

func (*BusManager) ClearSyncPDOs

func (busManager *BusManager) ClearSyncPDOs() error

Abort pending TPDOs

func (*BusManager) Handle

func (busManager *BusManager) Handle(frame Frame)

Implements the FrameListener interface This handles all received CAN frames from Bus

func (*BusManager) Send

func (busManager *BusManager) Send(frame Frame) error

Send a CAN message from given buffer Limited error handling

func (*BusManager) SetRxFilters

func (busManager *BusManager) SetRxFilters()

Update rx filters in buffer

func (*BusManager) Subscribe

func (busManager *BusManager) Subscribe(ident uint32, mask uint32, rtr bool, callback FrameListener) error

Subscribe to a specific CAN ID

type CRC16

type CRC16 uint16

type EM

type EM struct {
	CANerrorStatusOld uint16

	Fifo                []EMFifo
	FifoWrPtr           byte
	FifoPpPtr           byte
	FifoOverflow        byte
	FifoCount           byte
	ProducerEnabled     bool
	NodeId              byte
	ProducerIdent       uint16
	InhibitEmTimeUs     uint32
	InhibitEmTimer      uint32
	EmergencyRxCallback func(ident uint16, errorCode uint16, errorRegister byte, errorBit byte, infoCode uint32)
	// contains filtered or unexported fields
}

func NewEM

func NewEM(
	busManager *BusManager,
	nodeId uint8,
	entry1001 *Entry,
	entry1014 *Entry,
	entry1015 *Entry,
	entry1003 *Entry,
	entryStatusBits *Entry,
) (*EM, error)

func (*EM) Error

func (emergency *EM) Error(setError bool, errorBit byte, errorCode uint16, infoCode uint32) error

Set or reset an error condition Function adds a new error to the history & error will be processed by Process function

func (*EM) ErrorReport

func (emergency *EM) ErrorReport(errorBit byte, errorCode uint16, infoCode uint32) error

func (*EM) ErrorReset

func (emergency *EM) ErrorReset(errorBit byte, infoCode uint32) error

func (*EM) GetErrorRegister

func (emergency *EM) GetErrorRegister() byte

func (*EM) Handle

func (emergency *EM) Handle(frame Frame)

func (*EM) IsError

func (emergency *EM) IsError(errorBit byte) bool

type EMFifo

type EMFifo struct {
	// contains filtered or unexported fields
}

type Entry

type Entry struct {
	Index      uint16
	Name       string
	ObjectType uint8
	Object     any
	Extension  *Extension
	// contains filtered or unexported fields
}

An entry holds an OD entry, i.e. an OD object at a specific index An entry can be one of the following object types : variable, array, record or domain Depending on the object type it may contain some some objects

func (*Entry) AddExtension

func (entry *Entry) AddExtension(object any, read StreamReader, write StreamWriter) *Extension

Add an extension to entry and return created extension object can be any custom object

func (*Entry) AddMember

func (entry *Entry) AddMember(section *ini.Section, name string, nodeId uint8, subIndex uint8) error

Add a member to Entry, this is only possible for Record/Array objects

func (*Entry) GetRawData

func (entry *Entry) GetRawData(subIndex uint8, length uint16) ([]byte, error)

Getptr inside OD, similar to read

func (*Entry) PutUint16

func (entry *Entry) PutUint16(subIndex uint8, data uint16, origin bool) error

func (*Entry) PutUint32

func (entry *Entry) PutUint32(subIndex uint8, data uint32, origin bool) error

func (*Entry) PutUint64

func (entry *Entry) PutUint64(subIndex uint8, data uint64, origin bool) error

func (*Entry) PutUint8

func (entry *Entry) PutUint8(subIndex uint8, data uint8, origin bool) error

Set Uint8, 16 , 32 , 64

func (*Entry) SubCount

func (entry *Entry) SubCount() int

Get number of sub entries. Depends on type

func (*Entry) SubIndex

func (entry *Entry) SubIndex(subIndex any) (v *Variable, e error)

Get variable for a given sub index Subindex can be a string,int, or uint8 When using a string it will try to find the subindex according to the OD naming

func (*Entry) Uint16

func (entry *Entry) Uint16(subIndex uint8) (uint16, error)

Read Uint16 inside object dictionary

func (*Entry) Uint32

func (entry *Entry) Uint32(subIndex uint8) (uint32, error)

Read Uint32 inside object dictionary

func (*Entry) Uint64

func (entry *Entry) Uint64(subIndex uint8) (uint64, error)

Read Uint64 inside object dictionary

func (*Entry) Uint8

func (entry *Entry) Uint8(subIndex uint8) (uint8, error)

Read Uint8 inside object dictionary

type Extension

type Extension struct {
	Object any
	Read   StreamReader
	Write  StreamWriter
	// contains filtered or unexported fields
}

Extension object, is used for extending some functionnality to some OD entries Reader must be a custom reader for object Writer must be a custom reader for object

type Fifo

type Fifo struct {
	// contains filtered or unexported fields
}

Circular Fifo object used in some modules like SDO client

func NewFifo

func NewFifo(size uint16) *Fifo

func (*Fifo) AltBegin

func (fifo *Fifo) AltBegin(offset int) int

Alternate begin

func (*Fifo) AltFinish

func (fifo *Fifo) AltFinish(crc *CRC16)

func (*Fifo) AltGetOccupied

func (fifo *Fifo) AltGetOccupied() int

func (*Fifo) AltRead

func (fifo *Fifo) AltRead(buffer []byte) int

func (*Fifo) GetOccupied

func (fifo *Fifo) GetOccupied() int

func (*Fifo) GetSpace

func (fifo *Fifo) GetSpace() int

func (*Fifo) Read

func (fifo *Fifo) Read(buffer []byte, eof *bool) int

Read data from fifo and return number of bytes read

func (*Fifo) Reset

func (fifo *Fifo) Reset()

func (*Fifo) Write

func (fifo *Fifo) Write(buffer []byte, crc *CRC16) int

Write data to fifo

type FileInfo

type FileInfo struct {
	FileName         string
	FileVersion      string
	FileRevision     string
	LastEDS          string
	EDSVersion       string
	Description      string
	CreationTime     string
	CreationDate     string
	CreatedBy        string
	ModificationTime string
	ModificationDate string
	ModifiedBy       string
}

type FileObject

type FileObject struct {
	FilePath  string
	WriteMode int
	ReadMode  int
	File      *os.File
}

type Frame

type Frame struct {
	ID    uint32
	Flags uint8
	DLC   uint8
	Data  [8]byte
}

A CAN frame

func NewFrame

func NewFrame(id uint32, flags uint8, dlc uint8) Frame

type FrameListener

type FrameListener interface {
	Handle(frame Frame)
}

Interface used for handling a CAN frame, implementation specific : will depend on the bus type

type GWSDOReadResponse

type GWSDOReadResponse struct {
	Sequence string `json:"sequence"`
	Response string `json:"response"`
	Data     string `json:"data"`
	Length   string `json:"length,omitempty"`
}

type HBConsumer

type HBConsumer struct {
	AllMonitoredActive        bool
	AllMonitoredOperational   bool
	NMTisPreOrOperationalPrev bool
	// contains filtered or unexported fields
}

func NewHBConsumer

func NewHBConsumer(busManager *BusManager, em *EM, entry1016 *Entry) (*HBConsumer, error)

Initialize hearbeat consumer

type HBConsumerNode

type HBConsumerNode struct {
	NodeId uint8

	NMTState     int16
	NMTStatePrev int16
	HBState      uint8
	TimeoutTimer uint32
	TimeUs       uint32
	// contains filtered or unexported fields
}

Node specific hearbeat consumer part

func NewHBConsumerNode

func NewHBConsumerNode(index uint8, nodeId uint8, consumerTimeMs uint16) (*HBConsumerNode, error)

Initialize a single node consumer

func (*HBConsumerNode) Handle

func (nodeConsumer *HBConsumerNode) Handle(frame Frame)

Handle hearbeat reception specific to a node

type HTTPGatewayClient

type HTTPGatewayClient struct {
	BaseURL           string
	ApiVersion        string
	CurrentSequenceNb int
	NetworkId         int
}

func NewHTTPGatewayClient

func NewHTTPGatewayClient(baseURL string, apiVersion string, networkId int) *HTTPGatewayClient

func (*HTTPGatewayClient) Read

func (client *HTTPGatewayClient) Read(nodeId uint8, index uint16, subIndex uint8) (data string, length int, err error)

Read via SDO

type HTTPGatewayError

type HTTPGatewayError struct {
	Code int // Can be either an sdo abort code or a gateway error code
}

func (*HTTPGatewayError) Error

func (e *HTTPGatewayError) Error() string

type HTTPGatewayRequest

type HTTPGatewayRequest struct {
	// contains filtered or unexported fields
}

type HTTPGatewayResponse

type HTTPGatewayResponse struct {
	Sequence string `json:"sequence,omitempty"`
	Data     string `json:"data,omitempty"`
	Length   string `json:"length,omitempty"`
	Response string `json:"response,omitempty"`
}

type HTTPGatewayServer

type HTTPGatewayServer struct {
	// contains filtered or unexported fields
}

func NewGateway

func NewGateway(defaultNetworkId uint16, defaultNodeId uint8, sdoUploadBufferSize int, network *Network) *HTTPGatewayServer

Create a new gateway

func (*HTTPGatewayServer) ListenAndServe

func (gateway *HTTPGatewayServer) ListenAndServe(addr string) error

type LocalNode

type LocalNode struct {
	*BaseNode
	NodeIdUnconfigured bool
	NMT                *NMT
	HBConsumer         *HBConsumer
	SDOclients         []*SDOClient
	SDOServers         []*SDOServer
	TPDOs              []*TPDO
	RPDOs              []*RPDO
	SYNC               *SYNC
	EM                 *EM
	TIME               *TIME
}

func NewLocalNode

func NewLocalNode(
	busManager *BusManager,
	od *ObjectDictionary,
	nmt *NMT,
	emergency *EM,
	nodeId uint8,
	nmtControl uint16,
	firstHbTimeMs uint16,
	sdoServerTimeoutMs uint32,
	sdoClientTimeoutMs uint32,
	blockTransferEnabled bool,
	statusBits *Entry,

) (*LocalNode, error)

Create a new local node

func (*LocalNode) ProcessMain

func (node *LocalNode) ProcessMain(enableGateway bool, timeDifferenceUs uint32, timerNextUs *uint32) uint8

Process canopen objects that are not RT Does not process SYNC and PDOs

func (*LocalNode) ProcessRPDO

func (node *LocalNode) ProcessRPDO(syncWas bool, timeDifferenceUs uint32, timerNextUs *uint32)

func (*LocalNode) ProcessSync

func (node *LocalNode) ProcessSync(timeDifferenceUs uint32, timerNextUs *uint32) bool

func (*LocalNode) ProcessTPDO

func (node *LocalNode) ProcessTPDO(syncWas bool, timeDifferenceUs uint32, timerNextUs *uint32)

type NMT

type NMT struct {
	// contains filtered or unexported fields
}

func NewNMT

func NewNMT(
	busManager *BusManager,
	emergency *EM,
	nodeId uint8,
	control uint16,
	firstHbTimeMs uint16,
	canIdNmtTx uint16,
	canIdNmtRx uint16,
	canIdHbTx uint16,
	entry1017 *Entry,
) (*NMT, error)

func (*NMT) GetInternalState

func (nmt *NMT) GetInternalState() uint8

func (*NMT) Handle

func (nmt *NMT) Handle(frame Frame)

func (*NMT) SendCommand

func (nmt *NMT) SendCommand(command NMTCommand, nodeId uint8) error

Send an NMT command to the network

func (*NMT) SendInternalCommand

func (nmt *NMT) SendInternalCommand(command uint8)

Send NMT command to self, don't send on network

type NMTCommand

type NMTCommand uint8
const (
	NMT_NO_COMMAND            NMTCommand = 0
	NMT_ENTER_OPERATIONAL     NMTCommand = 1
	NMT_ENTER_STOPPED         NMTCommand = 2
	NMT_ENTER_PRE_OPERATIONAL NMTCommand = 128
	NMT_RESET_NODE            NMTCommand = 129
	NMT_RESET_COMMUNICATION   NMTCommand = 130
)

type Network

type Network struct {
	Nodes map[uint8]Node
	// contains filtered or unexported fields
}

func NewNetwork

func NewNetwork(bus Bus) Network

func (*Network) AddNode

func (network *Network) AddNode(nodeId uint8, od any, useLocal bool) (*RemoteNode, error)

Add a remote node with a given OD Can be either a string : path to OD or OD object This function will load and parse Object dictionnary (OD) into memory If already present, OD will be overwritten User can then access the node via OD naming A same OD can be used for multiple nodes

func (*Network) AddNodeFromSDO

func (network *Network) AddNodeFromSDO(
	nodeId uint8,
	formatHandlerCallback func(formatType uint8, reader io.Reader) (*ObjectDictionary, error),
) error

Same as AddNode, except od is downloaded from remote node

func (*Network) Command

func (network *Network) Command(nodeId uint8, nmtCommand NMTCommand) error

Send NMT commands to remote nodes Id 0 is used as a broadcast command i.e. affects all nodes

func (*Network) Configurator

func (network *Network) Configurator(nodeId uint8) NodeConfigurator

Create a node configurator This uses the network sdoclient

func (*Network) Connect

func (network *Network) Connect(args ...any) error

Connects to network and initialize master functionnality Custom CAN backend is possible using "Bus" interface Otherwise it expects an interface name, channel and bitrate

func (*Network) CreateNode

func (network *Network) CreateNode(nodeId uint8, od any) (*LocalNode, error)

Create a local CANopen compliant node with a given OD Can be either a string : path to OD or OD object

func (*Network) Disconnect

func (network *Network) Disconnect()

Disconnects from CAN bus and stops cleanly everything

func (*Network) GetOD

func (network *Network) GetOD(nodeId uint8) (*ObjectDictionary, error)

Get OD for a specific node id

func (*Network) Read

func (network *Network) Read(nodeId uint8, index any, subindex any) (value any, e error)

Read an entry from a remote node index and subindex can either be strings or integers this method requires the corresponding node OD to be loaded Returned value can be either string, uint64, int64 or float64

func (*Network) ReadEDS

func (network *Network) ReadEDS(nodeId uint8,
	formatHandlerCallback func(formatType uint8, reader io.Reader) (*ObjectDictionary, error),
) (*ObjectDictionary, error)

Read object dictionary using object 1021 (EDS storage) Optional callback can be provided to perform unzip, untar etc if a specific storage format is used

func (*Network) ReadFloat

func (network *Network) ReadFloat(nodeId uint8, index any, subindex any) (value float64, e error)

Same as Read but enforces the returned type as float

func (*Network) ReadInt

func (network *Network) ReadInt(nodeId uint8, index any, subindex any) (value int64, e error)

Same as Read but enforces the returned type as int64

func (*Network) ReadRaw

func (network *Network) ReadRaw(nodeId uint8, index uint16, subIndex uint8, data []byte) (int, error)

Read an entry from a remote node this method does not require corresponding OD to be loaded value will be read as a raw byte slice does not support block transfer

func (*Network) ReadString

func (network *Network) ReadString(nodeId uint8, index any, subindex any) (value string, e error)

Same as Read but enforces the returned type as string

func (*Network) ReadUint

func (network *Network) ReadUint(nodeId uint8, index any, subindex any) (value uint64, e error)

Same as Read but enforces the returned type as uint64

func (*Network) Write

func (network *Network) Write(nodeId uint8, index any, subindex any, value any) error

Write an entry to a remote node index and subindex can either be strings or integers this method requires the corresponding node OD to be loaded value should correspond to the expected datatype

func (*Network) WriteRaw

func (network *Network) WriteRaw(nodeId uint8, index uint16, subIndex uint8, data []byte) error

Write an entry to a remote node this method does not require corresponding OD to be loaded value will be written as a raw byte slice does not support block transfer

type Node

type Node interface {
	ProcessTPDO(syncWas bool, timeDifferenceUs uint32, timerNextUs *uint32)
	ProcessRPDO(syncWas bool, timeDifferenceUs uint32, timerNextUs *uint32)
	ProcessSync(timeDifferenceUs uint32, timerNextUs *uint32) bool
	ProcessMain(enableGateway bool, timeDifferenceUs uint32, timerNextUs *uint32) uint8
	GetOD() *ObjectDictionary
	GetID() uint8
	GetState() uint8
	SetState(newState uint8)
	GetExitBackground() chan bool
	SetExitBackground(exit bool) // Exit background processing
	GetExit() chan bool
	SetExit(exit bool) // Exit node processing
}

type NodeConfigurator

type NodeConfigurator struct {
	RPDO PDOConfigurator
	TPDO PDOConfigurator
	SYNC SYNCConfigurator
}

func NewNodeConfigurator

func NewNodeConfigurator(nodeId uint8, client *SDOClient) NodeConfigurator

type ODR

type ODR int8
const (
	ODR_PARTIAL        ODR = -1
	ODR_OK             ODR = 0
	ODR_OUT_OF_MEM     ODR = 1
	ODR_UNSUPP_ACCESS  ODR = 2
	ODR_WRITEONLY      ODR = 3
	ODR_READONLY       ODR = 4
	ODR_IDX_NOT_EXIST  ODR = 5
	ODR_NO_MAP         ODR = 6
	ODR_MAP_LEN        ODR = 7
	ODR_PAR_INCOMPAT   ODR = 8
	ODR_DEV_INCOMPAT   ODR = 9
	ODR_HW             ODR = 10
	ODR_TYPE_MISMATCH  ODR = 11
	ODR_DATA_LONG      ODR = 12
	ODR_DATA_SHORT     ODR = 13
	ODR_SUB_NOT_EXIST  ODR = 14
	ODR_INVALID_VALUE  ODR = 15
	ODR_VALUE_HIGH     ODR = 16
	ODR_VALUE_LOW      ODR = 17
	ODR_MAX_LESS_MIN   ODR = 18
	ODR_NO_RESOURCE    ODR = 19
	ODR_GENERAL        ODR = 20
	ODR_DATA_TRANSF    ODR = 21
	ODR_DATA_LOC_CTRL  ODR = 22
	ODR_DATA_DEV_STATE ODR = 23
	ODR_OD_MISSING     ODR = 24
	ODR_NO_DATA        ODR = 25
	ODR_COUNT          ODR = 26
)

func (ODR) Error

func (odr ODR) Error() string

func (ODR) GetSDOAbordCode

func (result ODR) GetSDOAbordCode() SDOAbortCode

Get the associated abort code, if the code is not present in map, return ODR_DEV_INCOMPAT

type ObjectDictionary

type ObjectDictionary struct {
	// contains filtered or unexported fields
}

Object dictionary contains all node data

func NewOD

func NewOD() *ObjectDictionary

func ParseEDSFromFile

func ParseEDSFromFile(filePath string, nodeId uint8) (*ObjectDictionary, error)

Create an OD from a given file path on system

func ParseEDSFromRaw

func ParseEDSFromRaw(edsBytes []byte, nodeId uint8) (*ObjectDictionary, error)

Create an OD from raw bytes

func (*ObjectDictionary) AddFile

func (od *ObjectDictionary) AddFile(index uint16, indexName string, filePath string, readMode int, writeMode int) error

Add file like object entry to OD

func (*ObjectDictionary) AddRPDO

func (od *ObjectDictionary) AddRPDO(rpdoNb uint16) error

Add an RPDO entry to OD with defaults

func (*ObjectDictionary) AddSYNC

func (od *ObjectDictionary) AddSYNC()

Add a SYNC object with defaults This will add SYNC with 0x1005,0x1006,0x1007 & 0x1019

func (*ObjectDictionary) AddTPDO

func (od *ObjectDictionary) AddTPDO(tpdoNb uint16) error

Add a TPDO entry to OD with defaults

func (*ObjectDictionary) AddVariableList

func (od *ObjectDictionary) AddVariableList(index uint16, name string, varList *VariableList)

Adds a record/variable to OD

func (*ObjectDictionary) AddVariableType

func (od *ObjectDictionary) AddVariableType(
	index uint16,
	name string,
	datatype uint8,
	attribute uint8,
	value string,
) (*Variable, error)

Creates and adds a Variable to OD

func (*ObjectDictionary) Index

func (od *ObjectDictionary) Index(index any) *Entry

Get an entry corresponding to a given index Index can either be a string, int or uint16 This method does not return an error for chaining

type ObjectDictionaryInformation

type ObjectDictionaryInformation struct {
	// contains filtered or unexported fields
}

type PDOCommon

type PDOCommon struct {
	Valid bool

	IsRPDO bool
	// contains filtered or unexported fields
}

Common to TPDO & RPDO

func NewPDO

func NewPDO(
	od *ObjectDictionary,
	entry *Entry,
	isRPDO bool,
	em *EM,
	erroneoursMap *uint32,
) (*PDOCommon, error)

Create and initialize a common PDO object

func (*PDOCommon) Type

func (base *PDOCommon) Type() string

type PDOConfiguration

type PDOConfiguration struct {
	CanId            uint16
	TransmissionType uint8
	InhibitTime      uint16
	EventTimer       uint16
	Mappings         []PDOMapping
}

Holds a PDO configuration

type PDOConfigurator

type PDOConfigurator struct {
	// contains filtered or unexported fields
}

func NewRPDOConfigurator

func NewRPDOConfigurator(nodeId uint8, sdoClient *SDOClient) *PDOConfigurator

PDO configurator is used for configurating node PDOs It has helper functions for accessing the common PDO mandatory objects

func NewTPDOConfigurator

func NewTPDOConfigurator(nodeId uint8, sdoClient *SDOClient) *PDOConfigurator

func (*PDOConfigurator) ClearMappings

func (config *PDOConfigurator) ClearMappings(pdoNb uint16) error

Clear all the PDO mappings Technically clearing the actual map entries is not necessary but I find it cleaner

func (*PDOConfigurator) Disable

func (config *PDOConfigurator) Disable(pdoNb uint16) error

Disable PDO

func (*PDOConfigurator) Enable

func (config *PDOConfigurator) Enable(pdoNb uint16) error

Enable PDO

func (*PDOConfigurator) ReadCobId

func (config *PDOConfigurator) ReadCobId(pdoNb uint16) (uint32, error)

func (*PDOConfigurator) ReadConfiguration

func (config *PDOConfigurator) ReadConfiguration(pdoNb uint16) (PDOConfiguration, error)

Reads complete PDO configuration

func (*PDOConfigurator) ReadEnabled

func (config *PDOConfigurator) ReadEnabled(pdoNb uint16) (bool, error)

func (*PDOConfigurator) ReadEventTimer

func (config *PDOConfigurator) ReadEventTimer(pdoNb uint16) (uint16, error)

func (*PDOConfigurator) ReadInhibitTime

func (config *PDOConfigurator) ReadInhibitTime(pdoNb uint16) (uint16, error)

func (*PDOConfigurator) ReadMappings

func (config *PDOConfigurator) ReadMappings(pdoNb uint16) ([]PDOMapping, error)

func (*PDOConfigurator) ReadNbMappings

func (config *PDOConfigurator) ReadNbMappings(pdoNb uint16) (uint8, error)

func (*PDOConfigurator) ReadTransmissionType

func (config *PDOConfigurator) ReadTransmissionType(pdoNb uint16) (uint8, error)

func (*PDOConfigurator) WriteCanId

func (config *PDOConfigurator) WriteCanId(pdoNb uint16, canId uint16) error

func (*PDOConfigurator) WriteConfiguration

func (config *PDOConfigurator) WriteConfiguration(pdoNb uint16, conf PDOConfiguration) error

Update hole configuration

func (*PDOConfigurator) WriteEventTimer

func (config *PDOConfigurator) WriteEventTimer(pdoNb uint16, eventTimer uint16) error

func (*PDOConfigurator) WriteInhibitTime

func (config *PDOConfigurator) WriteInhibitTime(pdoNb uint16, inhibitTime uint16) error

func (*PDOConfigurator) WriteMappings

func (config *PDOConfigurator) WriteMappings(pdoNb uint16, mappings []PDOMapping) error

Write new PDO mapping Takes a list of objects to map and will fill them up in the given order This will first clear the current mapping

func (*PDOConfigurator) WriteTransmissionType

func (config *PDOConfigurator) WriteTransmissionType(pdoNb uint16, transType uint8) error

type PDOMapping

type PDOMapping struct {
	Index      uint16
	Subindex   uint8
	LengthBits uint8
}

type RPDO

type RPDO struct {
	RxNew        [RPDO_BUFFER_COUNT]bool
	RxData       [RPDO_BUFFER_COUNT][MAX_PDO_LENGTH]byte
	ReceiveError uint8

	Synchronous   bool
	TimeoutTimeUs uint32
	TimeoutTimer  uint32
	// contains filtered or unexported fields
}

func NewRPDO

func NewRPDO(
	busManager *BusManager,
	od *ObjectDictionary,
	em *EM,
	sync *SYNC,
	entry14xx *Entry,
	entry16xx *Entry,
	predefinedIdent uint16,
) (*RPDO, error)

func (*RPDO) Handle

func (rpdo *RPDO) Handle(frame Frame)

type RemoteNode

type RemoteNode struct {
	*BaseNode
	// contains filtered or unexported fields
}

func NewRemoteNode

func NewRemoteNode(
	busManager *BusManager,
	remoteOd *ObjectDictionary,
	remoteNodeId uint8,
	useLocal bool,
) (*RemoteNode, error)

Create a remote node

func (*RemoteNode) InitPDOs

func (node *RemoteNode) InitPDOs(useLocal bool) error

Initialize PDOs according to either local OD mapping or remote OD mapping A TPDO corresponds to an RPDO and vice-versa

func (*RemoteNode) ProcessMain

func (node *RemoteNode) ProcessMain(enableGateway bool, timeDifferenceUs uint32, timerNextUs *uint32) uint8

func (*RemoteNode) ProcessRPDO

func (node *RemoteNode) ProcessRPDO(syncWas bool, timeDifferenceUs uint32, timerNextUs *uint32)

func (*RemoteNode) ProcessSync

func (node *RemoteNode) ProcessSync(timeDifferenceUs uint32, timerNextUs *uint32) bool

func (*RemoteNode) ProcessTPDO

func (node *RemoteNode) ProcessTPDO(syncWas bool, timeDifferenceUs uint32, timerNextUs *uint32)

type SDOAbortCode

type SDOAbortCode uint32

Common defines to both SDO server and SDO client

const (
	SDO_ABORT_TOGGLE_BIT         SDOAbortCode = 0x05030000
	SDO_ABORT_TIMEOUT            SDOAbortCode = 0x05040000
	SDO_ABORT_CMD                SDOAbortCode = 0x05040001
	SDO_ABORT_BLOCK_SIZE         SDOAbortCode = 0x05040002
	SDO_ABORT_SEQ_NUM            SDOAbortCode = 0x05040003
	SDO_ABORT_CRC                SDOAbortCode = 0x05040004
	SDO_ABORT_OUT_OF_MEM         SDOAbortCode = 0x05040005
	SDO_ABORT_UNSUPPORTED_ACCESS SDOAbortCode = 0x06010000
	SDO_ABORT_WRITEONLY          SDOAbortCode = 0x06010001
	SDO_ABORT_READONLY           SDOAbortCode = 0x06010002
	SDO_ABORT_NOT_EXIST          SDOAbortCode = 0x06020000
	SDO_ABORT_NO_MAP             SDOAbortCode = 0x06040041
	SDO_ABORT_MAP_LEN            SDOAbortCode = 0x06040042
	SDO_ABORT_PRAM_INCOMPAT      SDOAbortCode = 0x06040043
	SDO_ABORT_DEVICE_INCOMPAT    SDOAbortCode = 0x06040047
	SDO_ABORT_HW                 SDOAbortCode = 0x06060000
	SDO_ABORT_TYPE_MISMATCH      SDOAbortCode = 0x06070010
	SDO_ABORT_DATA_LONG          SDOAbortCode = 0x06070012
	SDO_ABORT_DATA_SHORT         SDOAbortCode = 0x06070013
	SDO_ABORT_SUB_UNKNOWN        SDOAbortCode = 0x06090011
	SDO_ABORT_INVALID_VALUE      SDOAbortCode = 0x06090030
	SDO_ABORT_VALUE_HIGH         SDOAbortCode = 0x06090031
	SDO_ABORT_VALUE_LOW          SDOAbortCode = 0x06090032
	SDO_ABORT_MAX_LESS_MIN       SDOAbortCode = 0x06090036
	SDO_ABORT_NO_RESOURCE        SDOAbortCode = 0x060A0023
	SDO_ABORT_GENERAL            SDOAbortCode = 0x08000000
	SDO_ABORT_DATA_TRANSF        SDOAbortCode = 0x08000020
	SDO_ABORT_DATA_LOC_CTRL      SDOAbortCode = 0x08000021
	SDO_ABORT_DATA_DEV_STATE     SDOAbortCode = 0x08000022
	SDO_ABORT_DATA_OD            SDOAbortCode = 0x08000023
	SDO_ABORT_NO_DATA            SDOAbortCode = 0x08000024
)

func (SDOAbortCode) Error

func (abort SDOAbortCode) Error() string

type SDOClient

type SDOClient struct {
	NodeId uint8

	CobIdClientToServer uint32
	CobIdServerToClient uint32
	NodeIdServer        uint8
	Valid               bool
	Index               uint16
	Subindex            uint8
	Finished            bool
	SizeIndicated       uint32
	SizeTransferred     uint32
	State               SDOState
	TimeoutTimeUs       uint32
	TimeoutTimer        uint32

	RxNew                      bool
	Response                   SDOResponse
	Toggle                     uint8
	TimeoutTimeBlockTransferUs uint32
	TimeoutTimerBlock          uint32
	BlockSequenceNb            uint8
	BlockSize                  uint8
	BlockNoData                uint8
	BlockCRCEnabled            bool
	BlockDataUploadLast        [7]byte
	BlockCRC                   CRC16
	// contains filtered or unexported fields
}

func NewSDOClient

func NewSDOClient(
	busManager *BusManager,
	od *ObjectDictionary,
	nodeId uint8,
	timeoutMs uint32,
	entry1280 *Entry,
) (*SDOClient, error)

func (*SDOClient) Handle

func (client *SDOClient) Handle(frame Frame)

func (*SDOClient) ReadAll

func (client *SDOClient) ReadAll(nodeId uint8, index uint16, subindex uint8) ([]byte, error)

Read everything from a given index/subindex from node and return all bytes Similar to io.ReadAll

func (*SDOClient) ReadRaw

func (client *SDOClient) ReadRaw(nodeId uint8, index uint16, subindex uint8, data []byte) (int, error)

Read a given index/subindex from node into data Similar to io.Read

func (*SDOClient) ReadUint16

func (client *SDOClient) ReadUint16(nodeId uint8, index uint16, subindex uint8) (uint16, error)

func (*SDOClient) ReadUint32

func (client *SDOClient) ReadUint32(nodeId uint8, index uint16, subindex uint8) (uint32, error)

func (*SDOClient) ReadUint64

func (client *SDOClient) ReadUint64(nodeId uint8, index uint16, subindex uint8) (uint64, error)

func (*SDOClient) ReadUint8

func (client *SDOClient) ReadUint8(nodeId uint8, index uint16, subindex uint8) (uint8, error)

func (*SDOClient) WriteRaw

func (client *SDOClient) WriteRaw(nodeId uint8, index uint16, subindex uint8, data any, forceSegmented bool) error

Write to a given index/subindex to node using raw data Similar to io.Write

type SDOResponse

type SDOResponse struct {
	// contains filtered or unexported fields
}

func (*SDOResponse) GetAbortCode

func (response *SDOResponse) GetAbortCode() SDOAbortCode

func (*SDOResponse) GetBlockSize

func (response *SDOResponse) GetBlockSize() uint8

func (*SDOResponse) GetCRCClient

func (response *SDOResponse) GetCRCClient() CRC16

func (*SDOResponse) GetIndex

func (response *SDOResponse) GetIndex() uint16

func (*SDOResponse) GetNumberOfSegments

func (response *SDOResponse) GetNumberOfSegments() uint8

func (*SDOResponse) GetSubindex

func (response *SDOResponse) GetSubindex() uint8

func (*SDOResponse) GetToggle

func (response *SDOResponse) GetToggle() uint8

func (*SDOResponse) IsAbort

func (response *SDOResponse) IsAbort() bool

func (*SDOResponse) IsCRCEnabled

func (response *SDOResponse) IsCRCEnabled() bool

type SDOReturn

type SDOReturn int8

type SDOServer

type SDOServer struct {
	NodeId     uint8
	BusManager *BusManager

	CobIdClientToServer uint32
	CobIdServerToClient uint32
	Valid               bool
	Index               uint16
	Subindex            uint8
	Finished            bool
	SizeIndicated       uint32
	SizeTransferred     uint32
	State               SDOState
	TimeoutTimeUs       uint32
	TimeoutTimer        uint32

	RxNew                      bool
	Response                   SDOResponse
	Toggle                     uint8
	TimeoutTimeBlockTransferUs uint32
	TimeoutTimerBlock          uint32
	BlockSequenceNb            uint8
	BlockSize                  uint8
	BlockNoData                uint8
	BlockCRCEnabled            bool
	BlockDataUploadLast        [7]byte
	BlockCRC                   CRC16
	ErrorExtraInfo             error
	// contains filtered or unexported fields
}

func NewSDOServer

func NewSDOServer(
	busManager *BusManager,
	od *ObjectDictionary,
	nodeId uint8,
	timeoutMs uint32,
	entry12xx *Entry,
) (*SDOServer, error)

func (*SDOServer) Abort

func (server *SDOServer) Abort(abortCode SDOAbortCode)

Create & send abort on bus

func (*SDOServer) Handle

func (server *SDOServer) Handle(frame Frame)

Handle received messages

func (*SDOServer) InitRxTx

func (server *SDOServer) InitRxTx(busManager *BusManager, cobIdClientToServer uint32, cobIdServerToClient uint32) error

type SDOState

type SDOState uint8
const (
	SDO_STATE_IDLE                      SDOState = 0x00
	SDO_STATE_ABORT                     SDOState = 0x01
	SDO_STATE_DOWNLOAD_LOCAL_TRANSFER   SDOState = 0x10
	SDO_STATE_DOWNLOAD_INITIATE_REQ     SDOState = 0x11
	SDO_STATE_DOWNLOAD_INITIATE_RSP     SDOState = 0x12
	SDO_STATE_DOWNLOAD_SEGMENT_REQ      SDOState = 0x13
	SDO_STATE_DOWNLOAD_SEGMENT_RSP      SDOState = 0x14
	SDO_STATE_UPLOAD_LOCAL_TRANSFER     SDOState = 0x20
	SDO_STATE_UPLOAD_INITIATE_REQ       SDOState = 0x21
	SDO_STATE_UPLOAD_INITIATE_RSP       SDOState = 0x22
	SDO_STATE_UPLOAD_SEGMENT_REQ        SDOState = 0x23
	SDO_STATE_UPLOAD_SEGMENT_RSP        SDOState = 0x24
	SDO_STATE_DOWNLOAD_BLK_INITIATE_REQ SDOState = 0x51
	SDO_STATE_DOWNLOAD_BLK_INITIATE_RSP SDOState = 0x52
	SDO_STATE_DOWNLOAD_BLK_SUBBLOCK_REQ SDOState = 0x53
	SDO_STATE_DOWNLOAD_BLK_SUBBLOCK_RSP SDOState = 0x54
	SDO_STATE_DOWNLOAD_BLK_END_REQ      SDOState = 0x55
	SDO_STATE_DOWNLOAD_BLK_END_RSP      SDOState = 0x56
	SDO_STATE_UPLOAD_BLK_INITIATE_REQ   SDOState = 0x61
	SDO_STATE_UPLOAD_BLK_INITIATE_RSP   SDOState = 0x62
	SDO_STATE_UPLOAD_BLK_INITIATE_REQ2  SDOState = 0x63
	SDO_STATE_UPLOAD_BLK_SUBBLOCK_SREQ  SDOState = 0x64
	SDO_STATE_UPLOAD_BLK_SUBBLOCK_CRSP  SDOState = 0x65
	SDO_STATE_UPLOAD_BLK_END_SREQ       SDOState = 0x66
	SDO_STATE_UPLOAD_BLK_END_CRSP       SDOState = 0x67
)

type SDOWrite

type SDOWrite struct {
	Value    string `json:"value"`
	Datatype string `json:"datatype"`
}

type SYNC

type SYNC struct {
	RxNew                bool
	ReceiveError         uint8
	RxToggle             bool
	TimeoutError         uint8
	CounterOverflowValue uint8
	Counter              uint8
	SyncIsOutsideWindow  bool
	Timer                uint32

	IsProducer bool
	BusManager *BusManager
	// contains filtered or unexported fields
}

func NewSYNC

func NewSYNC(
	busManager *BusManager,
	emergency *EM,
	entry1005 *Entry,
	entry1006 *Entry,
	entry1007 *Entry,
	entry1019 *Entry,
) (*SYNC, error)

func (*SYNC) Handle

func (sync *SYNC) Handle(frame Frame)

type SYNCConfigurator

type SYNCConfigurator struct {
	// contains filtered or unexported fields
}

func NewSYNCConfigurator

func NewSYNCConfigurator(nodeId uint8, sdoClient *SDOClient) *SYNCConfigurator

func (*SYNCConfigurator) ProducerDisable

func (config *SYNCConfigurator) ProducerDisable() error

func (*SYNCConfigurator) ProducerEnable

func (config *SYNCConfigurator) ProducerEnable() error

func (*SYNCConfigurator) ReadCobId

func (config *SYNCConfigurator) ReadCobId() (cobId uint32, err error)

func (*SYNCConfigurator) ReadCommunicationPeriod

func (config *SYNCConfigurator) ReadCommunicationPeriod() (uint32, error)

func (*SYNCConfigurator) ReadCounterOverflow

func (config *SYNCConfigurator) ReadCounterOverflow() (uint8, error)

func (*SYNCConfigurator) ReadWindowLengthPdos

func (config *SYNCConfigurator) ReadWindowLengthPdos() (uint32, error)

func (*SYNCConfigurator) WriteCanId

func (config *SYNCConfigurator) WriteCanId(canId uint16) error

Change sync can id, sync should be disabled before changing this

func (*SYNCConfigurator) WriteCommunicationPeriod

func (config *SYNCConfigurator) WriteCommunicationPeriod(periodUs uint32) error

func (*SYNCConfigurator) WriteCounterOverflow

func (config *SYNCConfigurator) WriteCounterOverflow(counter uint8) error

Sync should have communication period of 0 before changing this

func (*SYNCConfigurator) WriteWindowLengthPdos

func (config *SYNCConfigurator) WriteWindowLengthPdos(windowPeriodUs uint32) error

type SocketcanBus

type SocketcanBus struct {
	// contains filtered or unexported fields
}

func NewSocketcanBus

func NewSocketcanBus(name string) (*SocketcanBus, error)

func (*SocketcanBus) Connect

func (socketcan *SocketcanBus) Connect(...any) error

"Connect" implementation of Bus interface

func (*SocketcanBus) Disconnect

func (socketcan *SocketcanBus) Disconnect() error

"Disconnect" implementation of Bus interface

func (*SocketcanBus) Handle

func (socketcan *SocketcanBus) Handle(frame can.Frame)

brutella/can specific "Handle" implementation

func (*SocketcanBus) Send

func (socketcan *SocketcanBus) Send(frame Frame) error

"Send" implementation of Bus interface

func (*SocketcanBus) Subscribe

func (socketcan *SocketcanBus) Subscribe(rxCallback FrameListener) error

"Subscribe" implementation of Bus interface

type Stream

type Stream struct {
	Data       []byte
	DataOffset uint32
	DataLength uint32
	Object     any // Custom objects can be used when using an OD extension
	Attribute  uint8
	Subindex   uint8
}

A Stream to an OD entry

type StreamReader

type StreamReader func(stream *Stream, buffer []byte, countRead *uint16) error

type StreamWriter

type StreamWriter func(stream *Stream, buffer []byte, countWritten *uint16) error

type Streamer

type Streamer struct {
	// contains filtered or unexported fields
}

Streamer is created before accessing an OD entry It creates a buffer from OD Data []byte slice and provides a default reader and a default writer

func NewStreamer

func NewStreamer(entry *Entry, subIndex uint8, origin bool) (*Streamer, error)

Create an object streamer for a given od entry + subindex

func (*Streamer) Read

func (streamer *Streamer) Read(b []byte) (n int, err error)

Implements io.Reader

func (*Streamer) Write

func (streamer *Streamer) Write(b []byte) (n int, err error)

Implements io.Writer

type TIME

type TIME struct {
	RawTimestamp       [6]byte
	Ms                 uint32 // Milliseconds after midnight
	Days               uint16 // Days since 1st january 1984
	ResidualUs         uint16 // Residual Us calculated when processed
	IsConsumer         bool
	IsProducer         bool
	RxNew              bool
	ProducerIntervalMs uint32
	ProducerTimerMs    uint32
	// contains filtered or unexported fields
}

func NewTIME

func NewTIME(busManager *BusManager, entry1012 *Entry, producerIntervalMs uint32) (*TIME, error)

func (*TIME) Handle

func (time *TIME) Handle(frame Frame)

func (*TIME) SetInternalTime

func (time_obj *TIME) SetInternalTime()

Sets the internal time

type TPDO

type TPDO struct {
	TransmissionType uint8
	SendRequest      bool

	SyncStartValue uint8
	SyncCounter    uint8
	InhibitTimeUs  uint32
	EventTimeUs    uint32
	InhibitTimer   uint32
	EventTimer     uint32
	// contains filtered or unexported fields
}

func NewTPDO

func NewTPDO(
	busManager *BusManager,
	od *ObjectDictionary,
	em *EM,
	sync *SYNC,
	entry18xx *Entry,
	entry1Axx *Entry,
	predefinedIdent uint16,

) (*TPDO, error)

Create a new TPDO

func (*TPDO) Send

func (tpdo *TPDO) Send() error

Send TPDO object

type Variable

type Variable struct {
	Name           string
	DataType       byte
	Attribute      uint8 // Attribute contains the access type and pdo mapping info
	ParameterValue string

	StorageLocation string
	LowLimit        int
	HighLimit       int
	SubIndex        uint8
	// contains filtered or unexported fields
}

OD object used to store a "VAR" or "DOMAIN" object type

func NewVariable

func NewVariable(
	subindex uint8,
	name string,
	datatype uint8,
	attribute uint8,
	value string,
) (*Variable, error)

Create a new variable

func NewVariableFromSection

func NewVariableFromSection(
	section *ini.Section,
	name string,
	nodeId uint8,
	index uint16,
	subindex uint8,
) (*Variable, error)

Create variable from section entry

func (*Variable) DataLength

func (variable *Variable) DataLength() uint32

Return number of bytes

func (*Variable) DefaultValue

func (variable *Variable) DefaultValue() []byte

Return default value as byte slice

type VariableList

type VariableList struct {
	Variables []Variable
	// contains filtered or unexported fields
}

OD object used to store a "RECORD" or "ARRAY" object type

func NewArray

func NewArray(length uint8) *VariableList

func NewRecord

func NewRecord() *VariableList

func (*VariableList) AddSubObject

func (rec *VariableList) AddSubObject(
	subindex uint8,
	name string,
	datatype uint8,
	attribute uint8,
	value string,
) (*Variable, error)

func (*VariableList) GetSubObject

func (rec *VariableList) GetSubObject(subindex uint8) (*Variable, error)

type VirtualCanBus

type VirtualCanBus struct {
	// contains filtered or unexported fields
}

func NewVirtualCanBus

func NewVirtualCanBus(channel string) *VirtualCanBus

func (*VirtualCanBus) Connect

func (client *VirtualCanBus) Connect(...any) error

"Connect" to server e.g. localhost:18000

func (*VirtualCanBus) Disconnect

func (client *VirtualCanBus) Disconnect() error

"Disconnect" from server

func (*VirtualCanBus) Recv

func (client *VirtualCanBus) Recv() (*Frame, error)

Receive new CAN message

func (*VirtualCanBus) Send

func (client *VirtualCanBus) Send(frame Frame) error

"Send" implementation of Bus interface

func (*VirtualCanBus) Subscribe

func (client *VirtualCanBus) Subscribe(framehandler FrameListener) error

"Subscribe" implementation of Bus interface

Directories

Path Synopsis
cmd

Jump to

Keyboard shortcuts

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