Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions pstop_c/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,19 @@ cmake_minimum_required(VERSION 3.12)
project(PSTOP C)

add_subdirectory(pstop)
add_subdirectory(transport)

add_executable(machine_app
examples/machine/machine_app.c
)

target_include_directories(machine_app PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}/pstop/include
${CMAKE_CURRENT_SOURCE_DIR}/transport/include
include
)

target_link_libraries(machine_app PUBLIC
pstop
transport_udp
)
70 changes: 70 additions & 0 deletions pstop_c/examples/machine/machine_app.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@

// SPDX-FileCopyrightText: 2026 Polymath Robotics, Inc.
// SPDX-License-Identifier: Apache-2.0

#include <stdio.h>

#include "transport/udp/udp_transport.h"
#include "pstop/machine.h"
#include "pstop/pstop_msg.h"

pstop_application_t pstop_app;

#define MAX_CLIENTS 3U

pstop_client_data_t pstop_clients[MAX_CLIENTS];

pstop_machine_t machine;

udp_transport_data_t udp_transport;

int is_operator_allowed(const device_id_t *device_id)
{
return 1;
}

int
main(int argc, char *argv[])
{
transport_init_udp(&udp_transport);
pstop_application_init(&pstop_app);

pstop_app.app_config.default_timeout_ms = 1000U;
pstop_app.operator_allowed_cb = is_operator_allowed;

machine_init(&machine, &pstop_app, pstop_clients, MAX_CLIENTS);

int result = transport_udp_open(&udp_transport, "localhost", 8890);
if(result < 0) {
fprintf(stderr, "Unable to open UDP: %d\n", result);
return -1;
}

uint8_t reqbytes[PSTOP_MESSAGE_SIZE];
uint8_t respbytes[PSTOP_MESSAGE_SIZE];

pstop_msg_t req_msg;
pstop_msg_t resp_msg;
pstop_msg_t *resp_msg_ptr = &resp_msg;

fprintf(stderr, "Connected to localhost:8890\n");
while(1) {
struct sockaddr_storage client;
result = transport_udp_read(&udp_transport, reqbytes, PSTOP_MESSAGE_SIZE, &client);

if(result == PSTOP_MESSAGE_SIZE) {
pstop_message_encode(&req_msg, reqbytes);

pstop_error_t error = machine.handle_protocol_message_cb(&machine, &req_msg, &resp_msg_ptr);
if(resp_msg_ptr != NULL) {
pstop_message_encode(&resp_msg, respbytes);
transport_udp_write(&udp_transport, respbytes, PSTOP_MESSAGE_SIZE, (struct sockaddr_in *)&client);
}
}
machine.check_heartbeats_cb(&machine);
}

transport_udp_close(&udp_transport);

return 0;
}
1 change: 1 addition & 0 deletions pstop_c/pstop/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ add_executable(pstop_test
test/src/pstop/machine_test.c
test/src/pstop/machine_timeout_test.c
test/src/pstop/pstop_client_test.c
test/src/pstop/pstop_msg_test.c

test/src/pstop/test_utils.c

Expand Down
2 changes: 2 additions & 0 deletions pstop_c/pstop/include/pstop/device_id.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ typedef struct {
*/
void device_id_init(device_id_t *device_id);

void device_id_set_bytes(device_id_t *device_id, const uint8_t *data);

/**
* Copies the device ID from id to device_id.
*/
Expand Down
27 changes: 20 additions & 7 deletions pstop_c/pstop/include/pstop/pstop_msg.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,25 @@ typedef uint8_t message_type_t;
#define PSTOP_MESSAGE_STOP 1U
#define PSTOP_MESSAGE_BOND 2U
#define PSTOP_MESSAGE_UNBOND 3U
#define PSTOP_MESSAGE_UNKNOWN 0xFFU
#define PSTOP_MESSAGE_UNKNOWN 0x0FU

#define PSTOP_MESSAGE_SIZE 64U

/**
* A PSTOP message object. With enough information
* to provide basic black channel support.
*/
typedef struct {
/**
* Version of this message. Currently just 0x0
*/
uint8_t version;

/**
* Type of message.
*/
message_type_t message;

/**
* The timestamp (in milliseconds) of this message.
*/
Expand All @@ -45,7 +57,7 @@ typedef struct {

/**
* A timeout in milliseconds that we expect to receive heartbeats from
* this machine. Only valiud when sent from machine to operator.
* this machine. Only valid when sent from machine to operator.
*/
uint32_t heartbeat_timeout;

Expand All @@ -60,11 +72,6 @@ typedef struct {
*/
uint32_t received_counter;

/**
* The type of message.
*/
message_type_t message;

/**
* a CRC-16 checksum of the above values.
*/
Expand All @@ -78,4 +85,10 @@ uint16_t pstop_calculate_checksum(const pstop_msg_t *msg);

pstop_error_t pstop_is_message_valid(const pstop_msg_t *msg);

/**
* Network encoding/decoding functions
*/
void pstop_message_decode(pstop_msg_t *msg, const uint8_t *data);
void pstop_message_encode(const pstop_msg_t *msg, uint8_t *data);

#endif /* PSTOP_PSTOP_MSG_H */
6 changes: 6 additions & 0 deletions pstop_c/pstop/src/pstop/device_id.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@ device_id_init(device_id_t *device_id)
memset(device_id->data, 0, sizeof(device_id_t));
}

void
device_id_set_bytes(device_id_t *device_id, const uint8_t *data)
{
memcpy(device_id->data, data, DEVICE_ID_LENGTH);
}

void
device_id_copy(device_id_t *device_id, const device_id_t *id)
{
Expand Down
2 changes: 1 addition & 1 deletion pstop_c/pstop/src/pstop/pstop_application.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ pstop_application_config_init(pstop_application_config_t *config)
{
config->default_timeout_ms = 100U;
config->max_lost_messages = 1U;
config->max_missed_heartbeats = 0U;
config->max_missed_heartbeats = 1U;
}

void
Expand Down
Loading
Loading