Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

added DroneCAN parameter system #46

Merged
merged 7 commits into from
Sep 14, 2022
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ git-version.h
*.bin
*.elf
*.log
romfs_files.h
8 changes: 8 additions & 0 deletions RemoteIDModule/BLE_TX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@ static BLEMultiAdvertising advert(3);

bool BLE_TX::init(void)
{
if (initialised) {
return true;
}
initialised = true;
BLEDevice::init("");

// generate random mac address
Expand Down Expand Up @@ -102,6 +106,8 @@ bool BLE_TX::init(void)

bool BLE_TX::transmit_legacy_name(ODID_UAS_Data &UAS_data)
{
init();

//set BLE name
uint8_t legacy_name_payload[36];
char legacy_name[28] {};
Expand All @@ -125,6 +131,7 @@ bool BLE_TX::transmit_legacy_name(ODID_UAS_Data &UAS_data)

bool BLE_TX::transmit_longrange(ODID_UAS_Data &UAS_data)
{
init();
// create a packed UAS data message
uint8_t payload[250];
int length = odid_message_build_pack(&UAS_data, payload, 255);
Expand Down Expand Up @@ -153,6 +160,7 @@ bool BLE_TX::transmit_longrange(ODID_UAS_Data &UAS_data)

bool BLE_TX::transmit_legacy(ODID_UAS_Data &UAS_data)
{
init();
static uint8_t legacy_phase = 0;
int legacy_length = 0;
// setup ASTM header
Expand Down
1 change: 1 addition & 0 deletions RemoteIDModule/BLE_TX.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class BLE_TX : public Transmitter {
bool transmit_legacy(ODID_UAS_Data &UAS_data);

private:
bool initialised;
uint8_t msg_counters[ODID_MSG_COUNTER_AMOUNT];
uint8_t legacy_payload[36];
uint8_t longrange_payload[250];
Expand Down
159 changes: 152 additions & 7 deletions RemoteIDModule/DroneCAN.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,28 @@
#include "version.h"
#include <time.h>
#include "DroneCAN.h"
#include "parameters.h"

#include <canard.h>
#include <uavcan.protocol.NodeStatus.h>
#include <uavcan.protocol.GetNodeInfo.h>
#include <uavcan.protocol.RestartNode.h>
#include <uavcan.protocol.dynamic_node_id.Allocation.h>
#include <uavcan.protocol.param.GetSet.h>
#include <dronecan.remoteid.BasicID.h>
#include <dronecan.remoteid.Location.h>
#include <dronecan.remoteid.SelfID.h>
#include <dronecan.remoteid.System.h>
#include <dronecan.remoteid.OperatorID.h>
#include <dronecan.remoteid.ArmStatus.h>

#define BOARD_ID 10001
#ifndef CAN_BOARD_ID
#define CAN_BOARD_ID 10001
#endif

#ifndef CAN_APP_NODE_NAME
#define CAN_APP_NODE_NAME "ArduPilot RemoteIDModule"
#endif
#define CAN_DEFAULT_NODE_ID 0 // use DNA

#define UNUSED(x) (void)(x)

Expand All @@ -41,9 +46,9 @@ void DroneCAN::init(void)

canardInit(&canard, (uint8_t *)canard_memory_pool, sizeof(canard_memory_pool),
onTransferReceived_trampoline, shouldAcceptTransfer_trampoline, NULL);
#if CAN_DEFAULT_NODE_ID
canardSetLocalNodeID(&canard, CAN_DEFAULT_NODE_ID);
#endif
if (g.can_node > 0 && g.can_node < 128) {
canardSetLocalNodeID(&canard, g.can_node);
}
canard.user_reference = (void*)this;
}

Expand Down Expand Up @@ -144,6 +149,9 @@ void DroneCAN::onTransferReceived(CanardInstance* ins,
Serial.printf("Got OperatorID\n");
handle_OperatorID(transfer);
break;
case UAVCAN_PROTOCOL_PARAM_GETSET_ID:
handle_param_getset(ins, transfer);
break;
default:
//Serial.printf("reject %u\n", transfer->data_type_id);
break;
Expand Down Expand Up @@ -171,6 +179,7 @@ bool DroneCAN::shouldAcceptTransfer(const CanardInstance* ins,
ACCEPT_ID(DRONECAN_REMOTEID_SELFID);
ACCEPT_ID(DRONECAN_REMOTEID_OPERATORID);
ACCEPT_ID(DRONECAN_REMOTEID_SYSTEM);
ACCEPT_ID(UAVCAN_PROTOCOL_PARAM_GETSET);
return true;
}
//Serial.printf("%u: reject ID 0x%x\n", millis(), data_type_id);
Expand Down Expand Up @@ -334,8 +343,8 @@ void DroneCAN::handle_get_node_info(CanardInstance* ins, CanardRxTransfer* trans

readUniqueID(pkt.hardware_version.unique_id);

pkt.hardware_version.major = BOARD_ID >> 8;
pkt.hardware_version.minor = BOARD_ID & 0xFF;
pkt.hardware_version.major = CAN_BOARD_ID >> 8;
pkt.hardware_version.minor = CAN_BOARD_ID & 0xFF;
snprintf((char*)pkt.name.data, sizeof(pkt.name.data), "%s", CAN_APP_NODE_NAME);
pkt.name.len = strnlen((char*)pkt.name.data, sizeof(pkt.name.data));

Expand Down Expand Up @@ -534,6 +543,142 @@ void DroneCAN::handle_Location(CanardRxTransfer* transfer)
COPY_FIELD(timestamp_accuracy);
}

/*
handle parameter GetSet request
*/
void DroneCAN::handle_param_getset(CanardInstance* ins, CanardRxTransfer* transfer)
{
uavcan_protocol_param_GetSetRequest req;
if (uavcan_protocol_param_GetSetRequest_decode(transfer, &req)) {
return;
}

uavcan_protocol_param_GetSetResponse pkt {};

const Parameters::Param *vp = nullptr;

if (req.name.len != 0 && req.name.len > PARAM_NAME_MAX_LEN) {
vp = nullptr;
} else if (req.name.len != 0 && req.name.len <= PARAM_NAME_MAX_LEN) {
memcpy((char *)pkt.name.data, (char *)req.name.data, req.name.len);
vp = Parameters::find((char *)pkt.name.data);
} else {
vp = Parameters::find_by_index(req.index);
}
if (vp != nullptr && req.name.len != 0 && req.value.union_tag != UAVCAN_PROTOCOL_PARAM_VALUE_EMPTY) {
// param set
switch (vp->ptype) {
case Parameters::ParamType::UINT8:
if (req.value.union_tag != UAVCAN_PROTOCOL_PARAM_VALUE_INTEGER_VALUE) {
return;
}
vp->set_uint8(uint8_t(req.value.integer_value));
break;
case Parameters::ParamType::UINT32:
if (req.value.union_tag != UAVCAN_PROTOCOL_PARAM_VALUE_INTEGER_VALUE) {
return;
}
vp->set_uint32(uint32_t(req.value.integer_value));
break;
case Parameters::ParamType::FLOAT:
if (req.value.union_tag != UAVCAN_PROTOCOL_PARAM_VALUE_REAL_VALUE) {
return;
}
vp->set_float(req.value.real_value);
break;
case Parameters::ParamType::CHAR20: {
if (req.value.union_tag != UAVCAN_PROTOCOL_PARAM_VALUE_STRING_VALUE) {
return;
}
char v[21] {};
strncpy(v, (const char *)&req.value.string_value.data[0], req.value.string_value.len);
vp->set_char20(v);
break;
}
case Parameters::ParamType::CHAR64: {
if (req.value.union_tag != UAVCAN_PROTOCOL_PARAM_VALUE_STRING_VALUE) {
return;
}
char v[65] {};
strncpy(v, (const char *)&req.value.string_value.data[0], req.value.string_value.len);
vp->set_char64(v);
break;
}
default:
return;
}
}
if (vp != nullptr) {
switch (vp->ptype) {
case Parameters::ParamType::UINT8:
pkt.value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_INTEGER_VALUE;
pkt.value.integer_value = vp->get_uint8();
pkt.default_value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_INTEGER_VALUE;
pkt.default_value.integer_value = uint8_t(vp->default_value);
pkt.min_value.union_tag = UAVCAN_PROTOCOL_PARAM_NUMERICVALUE_INTEGER_VALUE;
pkt.min_value.integer_value = uint8_t(vp->min_value);
pkt.max_value.union_tag = UAVCAN_PROTOCOL_PARAM_NUMERICVALUE_INTEGER_VALUE;
pkt.max_value.integer_value = uint8_t(vp->max_value);
break;
case Parameters::ParamType::UINT32:
pkt.value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_INTEGER_VALUE;
pkt.value.integer_value = vp->get_uint32();
pkt.default_value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_INTEGER_VALUE;
pkt.default_value.integer_value = uint32_t(vp->default_value);
pkt.min_value.union_tag = UAVCAN_PROTOCOL_PARAM_NUMERICVALUE_INTEGER_VALUE;
pkt.min_value.integer_value = uint32_t(vp->min_value);
pkt.max_value.union_tag = UAVCAN_PROTOCOL_PARAM_NUMERICVALUE_INTEGER_VALUE;
pkt.max_value.integer_value = uint32_t(vp->max_value);
break;
case Parameters::ParamType::FLOAT:
pkt.value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_REAL_VALUE;
pkt.value.real_value = vp->get_float();
pkt.default_value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_REAL_VALUE;
pkt.default_value.real_value = vp->default_value;
pkt.min_value.union_tag = UAVCAN_PROTOCOL_PARAM_NUMERICVALUE_REAL_VALUE;
pkt.min_value.real_value = vp->min_value;
pkt.max_value.union_tag = UAVCAN_PROTOCOL_PARAM_NUMERICVALUE_REAL_VALUE;
pkt.max_value.real_value = vp->max_value;
break;
case Parameters::ParamType::CHAR20: {
pkt.value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_STRING_VALUE;
const char *s = vp->get_char20();
if (vp->flags & PARAM_FLAG_HIDDEN) {
s = "********";
}
strncpy((char*)pkt.value.string_value.data, s, sizeof(pkt.value.string_value.data));
pkt.value.string_value.len = strlen(s);
break;
}
case Parameters::ParamType::CHAR64: {
pkt.value.union_tag = UAVCAN_PROTOCOL_PARAM_VALUE_STRING_VALUE;
const char *s = vp->get_char64();
strncpy((char*)pkt.value.string_value.data, s, sizeof(pkt.value.string_value.data));
pkt.value.string_value.len = strlen(s);
break;
}
default:
return;
}
pkt.name.len = strlen(vp->name);
strncpy((char *)pkt.name.data, vp->name, sizeof(pkt.name.data));
}

uint8_t buffer[UAVCAN_PROTOCOL_PARAM_GETSET_RESPONSE_MAX_SIZE] {};
uint16_t total_size = uavcan_protocol_param_GetSetResponse_encode(&pkt, buffer);

canardRequestOrRespond(ins,
transfer->source_node_id,
UAVCAN_PROTOCOL_PARAM_GETSET_SIGNATURE,
UAVCAN_PROTOCOL_PARAM_GETSET_ID,
&transfer->transfer_id,
transfer->priority,
CanardResponse,
&buffer[0],
total_size);
}


#if 0
// xprintf is useful when debugging in C code such as libcanard
extern "C" {
Expand Down
1 change: 1 addition & 0 deletions RemoteIDModule/DroneCAN.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ class DroneCAN : public Transport {
void handle_OperatorID(CanardRxTransfer* transfer);
void handle_System(CanardRxTransfer* transfer);
void handle_Location(CanardRxTransfer* transfer);
void handle_param_getset(CanardInstance* ins, CanardRxTransfer* transfer);

public:
void onTransferReceived(CanardInstance* ins, CanardRxTransfer* transfer);
Expand Down
12 changes: 10 additions & 2 deletions RemoteIDModule/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,15 @@ headers:
@../scripts/git-version.sh
@cd .. && scripts/regen_headers.sh

ArduRemoteID-%.bin: *.cpp *.ino *.h
romfs_files.h: web/*.html web/js/*.js web/styles/*css web/images/*.jpg
@../scripts/make_romfs.py romfs_files.h web/*.html web/js/*.js web/styles/*css web/images/*.jpg

ArduRemoteID-%.bin: *.cpp *.ino *.h romfs_files.h
@echo "Building $* on $(CHIP)"
@BUILD_FLAGS="-DBOARD_$*"
@rm -rf build build-$*
@$(ARDUINO_CLI) compile -b esp32:esp32:$(CHIP) --export-binaries --build-property build.extra_flags=-DBOARD_$* --build-property upload.maximum_size=$(APP_PARTITION_SIZE) .
@$(ARDUINO_CLI) compile -b esp32:esp32:$(CHIP) --export-binaries --build-property build.extra_flags=-DBOARD_$* --build-property upload.maximum_size=$(APP_PARTITION_SIZE)
@cp build/esp32.esp32.$(CHIP)/RemoteIDModule.ino.bin ArduRemoteID_$*_OTA.bin
@echo "Merging $*"
@python3 $(ESPTOOL) --chip $(CHIP) merge_bin -o ArduRemoteID-$*.bin --flash_size 4MB 0x0 build/esp32.esp32.$(CHIP)/RemoteIDModule.ino.bootloader.bin 0x8000 build/esp32.esp32.$(CHIP)/RemoteIDModule.ino.partitions.bin 0xe000 $(ESP32_TOOLS)/partitions/boot_app0.bin 0x10000 build/esp32.esp32.$(CHIP)/RemoteIDModule.ino.bin
@mv build build-$*
Expand All @@ -58,6 +62,10 @@ upload-%: checkdev
@echo "Flashing ArduRemoteID-$*.bin"
$(ESPTOOL) --port $(SERDEV) write_flash 0x0 ArduRemoteID-$*.bin

uploadota-%: checkdev
@echo "Flashing ArduRemoteID-$*_OTA.bin"
$(ESPTOOL) --port $(SERDEV) write_flash 0x10000 ArduRemoteID_$*_OTA.bin

upload: upload-ESP32S3_DEV

clean:
Expand Down
Loading