Motion Master
Loading...
Searching...
No Matches
SPoE Client C++ Library

This documentation provides an overview of the SPoE Client, a static C++ library designed for efficient Ethernet communication with SOMANET Integro devices.

Note: This library requires your SOMANET Integro device to have Ethernet firmware installed.

The pre-built static library and examples are available in this public repository.

HTTP Server (ec2h)

An HTTP server application is provided that wraps this library, exposing its functionality via HTTP endpoints. A web-based user interface (UI) is also included. You can access both the server installer and the UI here: http://motion-master-console.synapticon.com/ethernet

Usage

To establish communication, the SOMANET Integro device must have a valid IP address. This can be configured in one of two ways:

  • Static Configuration: Assign a fixed IP address using EtherCAT communication.
  • Dynamic Configuration: Configuring a DHCP Server on your computer to automatically assign an IP address to the connected device.

Device Class Overview

mm::comm::spoe::Device

Handles TCP communication with SOMANET devices over Ethernet using a custom SPoE protocol.

This class provides methods for connecting to a remote server, sending messages, and receiving responses over a TCP connection using Boost.Asio. It manages the underlying socket, connection, and I/O operations required for client-server communication.

All message exchanges with the device are designed to be thread-safe.

Connection

Create an instance of the SPoE class by specifying the device's IP address and port number:

const std::string kIp = "192.168.100.5";
const int kPort = 8080;
Handles TCP communication with SOMANET devices over SPoE.
Definition: spoe.h:298
const uint16_t kPort
Definition: spoe_test.cc:14
const std::string kIp
Definition: spoe_test.cc:13

Then, connect to the device with:

auto connected = device.connect();

When the device is powered on, it will automatically transition to the OPERATIONAL state, which you can check with:

state = device.getState();
assert(state == 8); // Verify state is OPERATIONAL (8)
// Other states: INIT(1), PREOP(2), SAFEOP(4), OP(8), BOOT(3)

Most request functions support an optional expiryTime parameter of type std::chrono::steady_clock::duration. This specifies the maximum time to wait for a response from the device before a timeout error is triggered. For example:

try {
device.setState(0x02, std::chrono::milliseconds(1000));
} catch (const std::exception& e) {
std::cerr << "Failed to set state: " << e.what() << std::endl;
}

Parameters

To read a device parameter value (e.g., 0x6079: DC link circuit voltage), use:

std::vector<uint8_t> value = device.readSdo(0x6079, 0x01);
uint8_t * value
Definition: co_dictionary.h:9

The returned value is a vector of uint8_t representing a raw data buffer.

To write a device parameter value (e.g., 0x607A: Target position), use:

std::vector<uint8_t> value{0xe2, 0x04, 0x00, 0x00};
auto success = device.writeSdo(0x607a, 0x00, value);

There's a better, type-safe way to read and write parameter values. It requires first loading the parameters:

device.loadParameters(false); // Load parameter metadata without reading actual values

This loads parameter metadata from the device into an internal parameter map. Refer to the mm::comm::base::Parameter class for more details. Once the SPoE device has its parameters loaded, you can upload (read) and download (write) parameters using concrete types. These operations will automatically update the stored parameter value.

auto voltage = device.upload<uint32_t>(0x6079, 0x00); // Reads DC link circuit voltage as uint32_t
device.download<int32_t>(0x607a, 0x00, 543); // Writes 543 to target position

You can also retrieve a parameter and check its value after upload or download:

auto& parameter = device.findParameter(0x607a, 0x00);
assert(parameter.getValue<int32_t>() == 543);

Files

To read a file from the device:

std::vector<uint8_t> data = device.readFile(".hardware_description");

To write a file to the device:

std::vector<uint8_t> fileData(5000, 0xFF);
device.writeFile("ui.config.json", fileData);

If you write app_firmware.bin or com_firmware.bin, you must trigger a firmware update afterward:

device.triggerFirmwareUpdate();

To read the list of available files:

std::vector<std::string> list = device.readFileList(true); // strip file name size suffix

To remove a file from the device:

device.removeFile("ui.config.json");

Process Data

Process data exchange works similarly to SDO communication. You can either use raw data buffers or a simplified, parameter-based interface.

Raw buffer example:

std::vector<uint8_t> outputs(35, 0x00); // Create an RxPDO with 35 bytes
std::vector<uint8_t> inputs = device.sendAndReceiveProcessData(outputs);

With the simplified interface, start by loading parameter metadata:

device.loadParameters(false); // Load parameter metadata without reading actual values

Then retrieve and modify a parameter value, for example:

auto& parameter = device.findParameter(0x607a, 0x00);
parameter.setValue<int32_t>(123)

To perform the process data exchange and automatically update parameter values based on the PDO mapping:

device.exchangeProcessDataAndUpdateParameters();

This will send all mapped RxPDO parameter values, receive TxPDO values from the device, and update the corresponding local parameters.

Note: The PDO map is currently static and defined internally by the SpoeDevice. In future versions, it will be dynamically refreshed when loadParameters() is called.

Configuring a DHCP Server

Windows

  1. Download the DHCP Server

    Download the DHCP Server for Windows from https://www.dhcpserver.de/cms/download/.

  2. Extract the Server Files

    Extract the contents to C:\dhcpsrv2.5.2.

  3. Add Configuration File

    Copy the dhcpsrv.ini file into the extracted folder (C:\dhcpsrv2.5.2).

    [SETTINGS]
    IPPOOL_1=192.168.100.5-254
    IPBIND_1=192.168.100.1
    AssociateBindsToPools=1
    Trace=1
    DeleteOnRelease=0
    ExpiredLeaseTimeout=3600
    [GENERAL]
    LEASETIME=86400
    NODETYPE=8
    SUBNETMASK=255.255.255.0
    NEXTSERVER=192.168.100.1
    ROUTER_0=0.0.0.0
    [DNS-SETTINGS]
    EnableDNS=0
    [TFTP-SETTINGS]
    EnableTFTP=0
    ROOT=C:\dhcpsrv2.5.2\wwwroot
    WritePermission=0
    [HTTP-SETTINGS]
    EnableHTTP=1
    ROOT=C:\dhcpsrv2.5.2\wwwroot
    [40-49-8A-01-21-04]
    IPADDR=192.168.100.5
    AutoConfig=04/08/2025 13:03:01
    LeaseEnd=1744196934
  4. Configure Ethernet Adapter
    • Open Network Connections.
    • For your Ethernet adapter, open the properties for Internet Protocol Version 4 (TCP/IPv4).
    • Set the following static IP configuration:
      • IP Address: 192.168.100.1
      • Subnet Mask: 255.255.255.0
  5. Start the DHCP Server
    • Run C:\dhcpsrv2.5.2\dhcpsrv.exe.
    • Click Admin, then Service START, and finally Continue as tray app.
  6. Verify DHCP Assignment
    • Right-click the tray icon labeled DHCP Server v2.5.2.3 and select Open Status.
    • Under SERVER_0 > DHCP Clients, you should see the assigned IP 192.168.100.5, indicating the device successfully received its address from the DHCP server.

Linux

  1. Install ISC DHCP Server

    sudo apt update
    sudo apt install isc-dhcp-server
  2. Edit DHCP configurations

    sudo vim /etc/default/isc-dhcp-server
    INTERFACESv4="eth0"
    sudo vim /etc/dhcp/dhcpd.conf
    subnet 192.168.100.0 netmask 255.255.255.0 {
    range 192.168.100.10 192.168.100.20;
    option routers 192.168.100.1;
    option subnet-mask 255.255.255.0;
    option domain-name-servers 8.8.8.8, 8.8.4.4;
    }
    host special-client {
    hardware ethernet cc:96:e5:b5:43:52;
    fixed-address 192.168.100.10;
    }
  3. Assign Static IP address

    sudo nmcli connection modify eth0 ipv4.addresses 192.168.100.1/24
    sudo nmcli connection modify eth0 ipv4.gateway 192.168.100.1
    sudo nmcli connection modify eth0 ipv4.dns "8.8.8.8 8.8.4.4"
    sudo nmcli connection modify eth0 ipv4.method manual
    sudo nmcli connection up eth0

    Alternatively, configure it via Settings > Network > Wired.

    Verify the configuration:

    ip addr show eth0
    3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether cc:96:e5:b5:43:52 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.1/24 brd 192.168.100.255 scope global noprefixroute eth0
    valid_lft forever preferred_lft forever
    inet6 fe80::613d:20c3:e823:bdfd/64 scope link noprefixroute
    valid_lft forever preferred_lft forever
  4. Restart the DHCP server

    sudo systemctl restart isc-dhcp-server
    sudo systemctl status isc-dhcp-server

    If you encounter problems starting the DHCP server, try changing the permissions of the leases file:

    sudo chmod 777 /var/lib/dhcp/dhcpd.leases

    Next, verify that the device received the assigned IP address:

    ping 192.168.100.10

Installing Firmware Using integro_sock_client.py script

  1. Download the firmware from the following link:
    Firmware Download
  2. Unpack the downloaded package.
  3. Rename the com_motion-drive... file to test_com_firmware.bin.
  4. Move test_com_firmware.bin to the same directory where integro_sock_client.py is located.
  5. Execute the following command to write the boot file:
    python.exe .\integro_sock_client.py -t write_file_boot test_com_firmware.bin
  6. Run the command to update the firmware:
    python.exe .\integro_sock_client.py -t update_firmware

Notes

  • The default socket port is 8080.
  • Firmware versions can be read using the read file command:
    • Use cversion to retrieve the firmware version.
    • Use bversion to retrieve the bootloader version.

Links