From 312404730af32ba90f468bc1036ed236d198041c Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 24 Oct 2019 17:19:36 +0200 Subject: [PATCH 01/44] init gp sink table and send gp proxy comm mode to dongle gp proxy --- src/domain/ezsp-protocol/ezsp-enum.cpp | 181 ++++++++++++++++++- src/domain/zbmessage/zclheader.h | 6 + src/domain/zbmessage/zigbee-message.h | 3 +- src/domain/zigbee-tools/green-power-sink.cpp | 73 +++++++- src/domain/zigbee-tools/green-power-sink.h | 22 ++- src/example/CAppDemo.cpp | 10 +- src/example/mainEzspTest.cpp | 2 +- 7 files changed, 291 insertions(+), 6 deletions(-) diff --git a/src/domain/ezsp-protocol/ezsp-enum.cpp b/src/domain/ezsp-protocol/ezsp-enum.cpp index 7aac4cd8..25feea90 100644 --- a/src/domain/ezsp-protocol/ezsp-enum.cpp +++ b/src/domain/ezsp-protocol/ezsp-enum.cpp @@ -61,46 +61,225 @@ std::string CEzspEnum::EmberJoinMethodToString( EmberJoinMethod in ) std::string CEzspEnum::EEzspCmdToString( EEzspCmd in ) { const std::map MyEnumStrings { + /* Configuration Frames */ { EZSP_VERSION, "EZSP_VERSION" }, { EZSP_GET_CONFIGURATION_VALUE, "EZSP_GET_CONFIGURATION_VALUE" }, { EZSP_SET_CONFIGURATION_VALUE, "EZSP_SET_CONFIGURATION_VALUE" }, { EZSP_ADD_ENDPOINT, "EZSP_ADD_ENDPOINT" }, { EZSP_SET_POLICY, "EZSP_SET_POLICY" }, { EZSP_GET_POLICY, "EZSP_GET_POLICY" }, + { EZSP_SEND_PAN_ID_UPDATE, "EZSP_SEND_PAN_ID_UPDATE" }, { EZSP_GET_VALUE, "EZSP_GET_VALUE" }, + { EZSP_GET_EXTENDED_VALUE, "EZSP_GET_EXTENDED_VALUE" }, { EZSP_SET_VALUE, "EZSP_SET_VALUE" }, + { EZSP_SET_GPIO_CURRENT_CONFIGURATION, "EZSP_SET_GPIO_CURRENT_CONFIGURATION" }, + { EZSP_SET_GPIO_POWER_UP_DOWN_CONFIGURATION, "EZSP_SET_GPIO_POWER_UP_DOWN_CONFIGURATION" }, + { EZSP_SET_GPIO_RADIO_POWER_MASK, "EZSP_SET_GPIO_RADIO_POWER_MASK" }, + { EZSP_SET_CTUNE, "EZSP_SET_CTUNE" }, + { EZSP_GET_CTUNE, "EZSP_GET_CTUNE" }, + /* Utilities Frames */ { EZSP_NOP, "EZSP_NOP" }, + { EZSP_ECHO, "EZSP_ECHO" }, + { EZSP_INVALID_COMMAND, "EZSP_INVALID_COMMAND" }, + { EZSP_CALLBACK, "EZSP_CALLBACK" }, + { EZSP_NO_CALLBACKS, "EZSP_NO_CALLBACKS" }, + { EZSP_SET_TOKEN, "EZSP_SET_TOKEN" }, + { EZSP_GET_TOKEN, "EZSP_GET_TOKEN" }, + { EZSP_GET_MFG_TOKEN, "EZSP_GET_MFG_TOKEN" }, + { EZSP_SET_MFG_TOKEN, "EZSP_SET_MFG_TOKEN" }, + { EZSP_STACK_TOKEN_CHANGED_HANDLER, "EZSP_STACK_TOKEN_CHANGED_HANDLER" }, + { EZSP_GET_RANDOM_NUMBER, "EZSP_GET_RANDOM_NUMBER" }, + { EZSP_SET_TIMER, "EZSP_SET_TIMER" }, + { EZSP_GET_TIMER, "EZSP_GET_TIMER" }, { EZSP_TIMER_HANDLER, "EZSP_TIMER_HANDLER" }, - /*{ EZSP_DEBUG_HANDLER, "EZSP_DEBUG_HANDLER" },*/ + { EZSP_DEBUG_WRITE, "EZSP_DEBUG_WRITE" }, + { EZSP_READ_AND_CLEAR_COUNTERS, "EZSP_READ_AND_CLEAR_COUNTERS" }, + { EZSP_READ_COUNTERS, "EZSP_READ_COUNTERS" }, + { EZSP_COUNTER_ROLLOVER_HANDLER, "EZSP_COUNTER_ROLLOVER_HANDLER" }, + { EZSP_DELAY_TEST, "EZSP_DELAY_TEST" }, + { EZSP_GET_LIBRARY_STATUS, "EZSP_GET_LIBRARY_STATUS" }, + { EZSP_GET_XNCP_INFO, "EZSP_GET_XNCP_INFO" }, + { EZSP_CUSTOM_FRAME, "EZSP_CUSTOM_FRAME" }, + { EZSP_CUSTOM_FRAME_HANDLER, "EZSP_CUSTOM_FRAME_HANDLER" }, + { EZSP_GET_EUI64, "EZSP_GET_EUI64" }, + { EZSP_GET_NODE_ID, "EZSP_GET_NODE_ID" }, + { EZSP_GET_PHY_INTERFACE_COUNT, "EZSP_GET_PHY_INTERFACE_COUNT" }, + { EZSP_GET_TRUE_RANDOM_ENTROPY_SOURCE, "EZSP_GET_TRUE_RANDOM_ENTROPY_SOURCE" }, + /* Networking Frames */ + { EZSP_SET_MANUFACTURER_CODE, "EZSP_SET_MANUFACTURER_CODE" }, + { EZSP_SET_POWER_DESCRIPTOR, "EZSP_SET_POWER_DESCRIPTOR" }, + { EZSP_NETWORK_INIT, "EZSP_NETWORK_INIT" }, + { EZSP_NETWORK_STATE, "EZSP_NETWORK_STATE" }, { EZSP_STACK_STATUS_HANDLER, "EZSP_STACK_STATUS_HANDLER" }, + { EZSP_START_SCAN, "EZSP_START_SCAN" }, { EZSP_ENERGY_SCAN_RESULT_HANDLER, "EZSP_ENERGY_SCAN_RESULT_HANDLER" }, { EZSP_NETWORK_FOUND_HANDLER, "EZSP_NETWORK_FOUND_HANDLER" }, { EZSP_SCAN_COMPLETE_HANDLER, "EZSP_SCAN_COMPLETE_HANDLER" }, + { EZSP_UNUSED_PAN_ID_FOUND_HANDLER, "EZSP_UNUSED_PAN_ID_FOUND_HANDLER" }, + { EZSP_FIND_UNUSED_PAN_ID, "EZSP_FIND_UNUSED_PAN_ID" }, + { EZSP_STOP_SCAN, "EZSP_STOP_SCAN" }, + { EZSP_FORM_NETWORK, "EZSP_FORM_NETWORK" }, + { EZSP_JOIN_NETWORK, "EZSP_JOIN_NETWORK" }, + { EZSP_LEAVE_NETWORK, "EZSP_LEAVE_NETWORK" }, + { EZSP_FIND_AND_REJOIN_NETWORK, "EZSP_FIND_AND_REJOIN_NETWORK" }, + { EZSP_PERMIT_JOINING, "EZSP_PERMIT_JOINING" }, { EZSP_CHILD_JOIN_HANDLER, "EZSP_CHILD_JOIN_HANDLER" }, + { EZSP_ENERGY_SCAN_REQUEST, "EZSP_ENERGY_SCAN_REQUEST" }, + { EZSP_GET_NETWORK_PARAMETERS, "EZSP_GET_NETWORK_PARAMETERS" }, + { EZSP_GET_RADIO_PARAMETERS, "EZSP_GET_RADIO_PARAMETERS" }, + { EZSP_GET_PARENT_CHILD_PARAMETERS, "EZSP_GET_PARENT_CHILD_PARAMETERS" }, + { EZSP_GET_CHILD_DATA, "EZSP_GET_CHILD_DATA" }, + { EZSP_GET_SOURCE_ROUTE_TABLE_TOTAL_SIZE, "EZSP_GET_SOURCE_ROUTE_TABLE_TOTAL_SIZE" }, + { EZSP_GET_SOURCE_ROUTE_TABLE_FILLED_SIZE, "EZSP_GET_SOURCE_ROUTE_TABLE_FILLED_SIZE" }, + { EZSP_GET_SOURCE_ROUTE_TABLE_ENTRY, "EZSP_GET_SOURCE_ROUTE_TABLE_ENTRY" }, + { EZSP_GET_NEIGHBOR, "EZSP_GET_NEIGHBOR" }, + { EZSP_SET_ROUTING_SHORTCUT_THRESHOLD, "EZSP_SET_ROUTING_SHORTCUT_THRESHOLD" }, + { EZSP_GET_ROUTING_SHORTCUT_THRESHOLD, "EZSP_GET_ROUTING_SHORTCUT_THRESHOLD" }, + { EZSP_NEIGHBOR_COUNT, "EZSP_NEIGHBOR_COUNT" }, + { EZSP_GET_ROUTE_TABLE_ENTRY, "EZSP_GET_ROUTE_TABLE_ENTRY" }, + { EZSP_SET_RADIO_POWER, "EZSP_SET_RADIO_POWER" }, + { EZSP_SET_RADIO_CHANNEL, "EZSP_SET_RADIO_CHANNEL" }, + { EZSP_SET_CONCENTRATOR, "EZSP_SET_CONCENTRATOR" }, + { EZSP_SET_BROKEN_ROUTE_ERROR_CODE, "EZSP_SET_BROKEN_ROUTE_ERROR_CODE" }, + { EZSP_MULTI_PHY_START, "EZSP_MULTI_PHY_START" }, + { EZSP_MULTI_PHY_STOP, "EZSP_MULTI_PHY_STOP" }, + { EZSP_MULTI_PHY_SET_RADIO_POWER, "EZSP_MULTI_PHY_SET_RADIO_POWER" }, + { EZSP_SEND_LINK_POWER_DELTA_REQUEST, "EZSP_SEND_LINK_POWER_DELTA_REQUEST" }, + { EZSP_MULTI_PHY_SET_RADIO_CHANNEL, "EZSP_MULTI_PHY_SET_RADIO_CHANNEL" }, + { EZSP_GET_DUTY_CYCLE_STATE, "EZSP_GET_DUTY_CYCLE_STATE" }, + { EZSP_SET_DUTY_CYCLE_LIMITS_IN_STACK, "EZSP_SET_DUTY_CYCLE_LIMITS_IN_STACK" }, + { EZSP_GET_DUTY_CYCLE_LIMITS, "EZSP_GET_DUTY_CYCLE_LIMITS" }, + { EZSP_GET_CURRENT_DUTY_CYCLE, "EZSP_GET_CURRENT_DUTY_CYCLE" }, + { EZSP_DUTY_CYCLE_HANDLER, "EZSP_DUTY_CYCLE_HANDLER" }, + /* Binding Frames */ + { EZSP_CLEAR_BINDING_TABLE, "EZSP_CLEAR_BINDING_TABLE" }, + { EZSP_SET_BINDING, "EZSP_SET_BINDING" }, + { EZSP_GET_BINDING, "EZSP_GET_BINDING" }, + { EZSP_DELETE_BINDING, "EZSP_DELETE_BINDING" }, + { EZSP_BINDING_IS_ACTIVE, "EZSP_BINDING_IS_ACTIVE" }, + { EZSP_GET_BINDING_REMOTE_NODE_ID, "EZSP_GET_BINDING_REMOTE_NODE_ID" }, + { EZSP_SET_BINDING_REMOTE_NODE_ID, "EZSP_SET_BINDING_REMOTE_NODE_ID" }, { EZSP_REMOTE_SET_BINDING_HANDLER, "EZSP_REMOTE_SET_BINDING_HANDLER" }, { EZSP_REMOTE_DELETE_BINDING_HANDLER, "EZSP_REMOTE_DELETE_BINDING_HANDLER" }, + /* Messaging Frames */ + { EZSP_MAXIMUM_PAYLOAD_LENGTH, "EZSP_MAXIMUM_PAYLOAD_LENGTH" }, + { EZSP_SEND_UNICAST, "EZSP_SEND_UNICAST" }, + { EZSP_SEND_BROADCAST, "EZSP_SEND_BROADCAST" }, + { EZSP_PROXY_BROADCAST, "EZSP_PROXY_BROADCAST" }, + { EZSP_SEND_MULTICAST, "EZSP_SEND_MULTICAST" }, + { EZSP_SEND_MULTICAST_WITH_ALIAS, "EZSP_SEND_MULTICAST_WITH_ALIAS" }, + { EZSP_SEND_REPLY, "EZSP_SEND_REPLY" }, { EZSP_MESSAGE_SENT_HANDLER, "EZSP_MESSAGE_SENT_HANDLER" }, + { EZSP_SEND_MANY_TO_ONE_ROUTE_REQUEST, "EZSP_SEND_MANY_TO_ONE_ROUTE_REQUEST" }, + { EZSP_POLL_FOR_DATA, "EZSP_POLL_FOR_DATA" }, { EZSP_POLL_COMPLETE_HANDLER, "EZSP_POLL_COMPLETE_HANDLER" }, { EZSP_POLL_HANDLER, "EZSP_POLL_HANDLER" }, { EZSP_INCOMING_SENDER_EUI64_HANDLER, "EZSP_INCOMING_SENDER_EUI64_HANDLER" }, { EZSP_INCOMING_MESSAGE_HANDLER, "EZSP_INCOMING_MESSAGE_HANDLER" }, { EZSP_INCOMING_ROUTE_RECORD_HANDLER, "EZSP_INCOMING_ROUTE_RECORD_HANDLER" }, + { EZSP_CHANGE_SOURCE_ROUTE_HANDLER, "EZSP_CHANGE_SOURCE_ROUTE_HANDLER" }, + { EZSP_SET_SOURCE_ROUTE, "EZSP_SET_SOURCE_ROUTE" }, { EZSP_INCOMING_MANY_TO_ONE_ROUTE_REQUEST_HANDLER, "EZSP_INCOMING_MANY_TO_ONE_ROUTE_REQUEST_HANDLER" }, { EZSP_INCOMING_ROUTE_ERROR_HANDLER, "EZSP_INCOMING_ROUTE_ERROR_HANDLER" }, + { EZSP_ADDRESS_TABLE_ENTRY_IS_ACTIVE, "EZSP_ADDRESS_TABLE_ENTRY_IS_ACTIVE" }, + { EZSP_SET_ADDRESS_TABLE_REMOTE_EUI64, "EZSP_SET_ADDRESS_TABLE_REMOTE_EUI64" }, + { EZSP_SET_ADDRESS_TABLE_REMOTE_NODE_ID, "EZSP_SET_ADDRESS_TABLE_REMOTE_NODE_ID" }, + { EZSP_GET_ADDRESS_TABLE_REMOTE_EUI64, "EZSP_GET_ADDRESS_TABLE_REMOTE_EUI64" }, + { EZSP_GET_ADDRESS_TABLE_REMOTE_NODE_ID, "EZSP_GET_ADDRESS_TABLE_REMOTE_NODE_ID" }, + { EZSP_SET_EXTENDED_TIMEOUT, "EZSP_SET_EXTENDED_TIMEOUT" }, + { EZSP_GET_EXTENDED_TIMEOUT, "EZSP_GET_EXTENDED_TIMEOUT" }, + { EZSP_REPLACE_ADDRESS_TABLE_ENTRY, "EZSP_REPLACE_ADDRESS_TABLE_ENTRY" }, + { EZSP_LOOKUP_NODE_ID_BY_EUI64, "EZSP_LOOKUP_NODE_ID_BY_EUI64" }, + { EZSP_LOOKUP_EUI64_BY_NODE_ID, "EZSP_LOOKUP_EUI64_BY_NODE_ID" }, + { EZSP_GET_MULTICAST_TABLE_ENTRY, "EZSP_GET_MULTICAST_TABLE_ENTRY" }, + { EZSP_SET_MULTICAST_TABLE_ENTRY, "EZSP_SET_MULTICAST_TABLE_ENTRY" }, { EZSP_ID_CONFLICT_HANDLER, "EZSP_ID_CONFLICT_HANDLER" }, + { EZSP_WRITE_NODE_DATA, "EZSP_WRITE_NODE_DATA" }, + { EZSP_SEND_RAW_MESSAGE, "EZSP_SEND_RAW_MESSAGE" }, { EZSP_MAC_PASSTHROUGH_MESSAGE_HANDLER, "EZSP_MAC_PASSTHROUGH_MESSAGE_HANDLER" }, { EZSP_MAC_FILTER_MATCH_MESSAGE_HANDLER, "EZSP_MAC_FILTER_MATCH_MESSAGE_HANDLER" }, { EZSP_RAW_TRANSMIT_COMPLETE_HANDLER, "EZSP_RAW_TRANSMIT_COMPLETE_HANDLER" }, + { EZSP_SET_MAC_POLL_CCA_WAIT_TIME, "EZSP_SET_MAC_POLL_CCA_WAIT_TIME" }, + { EZSP_SET_BEACON_CLASSIFICATION_PARAMS, "EZSP_SET_BEACON_CLASSIFICATION_PARAMS" }, + { EZSP_GET_BEACON_CLASSIFICATION_PARAMS, "EZSP_GET_BEACON_CLASSIFICATION_PARAMS" }, + /* Security Frames */ + { EZSP_SET_INITIAL_SECURITY_STATE, "EZSP_SET_INITIAL_SECURITY_STATE" }, + { EZSP_GET_CURRENT_SECURITY_STATE, "EZSP_GET_CURRENT_SECURITY_STATE" }, + { EZSP_GET_KEY, "EZSP_GET_KEY" }, { EZSP_SWITCH_NETWORK_KEY_HANDLER, "EZSP_SWITCH_NETWORK_KEY_HANDLER" }, + { EZSP_GET_KEY_TABLE_ENTRY, "EZSP_GET_KEY_TABLE_ENTRY" }, + { EZSP_SET_KEY_TABLE_ENTRY, "EZSP_SET_KEY_TABLE_ENTRY" }, + { EZSP_FIND_KEY_TABLE_ENTRY, "EZSP_FIND_KEY_TABLE_ENTRY" }, + { EZSP_ADD_OR_UPDATE_KEY_TABLE_ENTRY, "EZSP_ADD_OR_UPDATE_KEY_TABLE_ENTRY" }, + { EZSP_SEND_TRUST_CENTER_LINK_KEY, "EZSP_SEND_TRUST_CENTER_LINK_KEY" }, + { EZSP_ERASE_KEY_TABLE_ENTRY, "EZSP_ERASE_KEY_TABLE_ENTRY" }, + { EZSP_CLEAR_KEY_TABLE, "EZSP_CLEAR_KEY_TABLE" }, + { EZSP_REQUEST_LINK_KEY, "EZSP_REQUEST_LINK_KEY" }, + { EZSP_UPDATE_TC_LINK_KEY, "EZSP_UPDATE_TC_LINK_KEY" }, { EZSP_ZIGBEE_KEY_ESTABLISHMENT_HANDLER, "EZSP_ZIGBEE_KEY_ESTABLISHMENT_HANDLER" }, + { EZSP_ADD_TRANSIENT_LINK_KEY, "EZSP_ADD_TRANSIENT_LINK_KEY" }, + { EZSP_CLEAR_TRANSIENT_LINK_KEYS, "EZSP_CLEAR_TRANSIENT_LINK_KEYS" }, + { EZSP_GET_TRANSIENT_LINK_KEY, "EZSP_GET_TRANSIENT_LINK_KEY" }, + { EZSP_GET_TRANSIENT_KEY_TABLE_ENTRY, "EZSP_GET_TRANSIENT_KEY_TABLE_ENTRY" }, + /* Trust Center Frames */ { EZSP_TRUST_CENTER_JOIN_HANDLER, "EZSP_TRUST_CENTER_JOIN_HANDLER" }, + { EZSP_BROADCAST_NEXT_NETWORK_KEY, "EZSP_BROADCAST_NEXT_NETWORK_KEY" }, + { EZSP_BROADCAST_NETWORK_KEY_SWITCH, "EZSP_BROADCAST_NETWORK_KEY_SWITCH" }, + { EZSP_BECOME_TRUST_CENTER, "EZSP_BECOME_TRUST_CENTER" }, + { EZSP_AES_MMO_HASH, "EZSP_AES_MMO_HASH" }, + { EZSP_REMOVE_DEVICE, "EZSP_REMOVE_DEVICE" }, + { EZSP_UNICAST_NWK_KEY_UPDATE, "EZSP_UNICAST_NWK_KEY_UPDATE" }, + /* Certificate Based Key Exchange (CBKE) */ + { EZSP_GENERATE_CBKE_KEYS, "EZSP_GENERATE_CBKE_KEYS" }, { EZSP_GENERATE_CBKE_KEYS_HANDLER, "EZSP_GENERATE_CBKE_KEYS_HANDLER" }, + { EZSP_CALCULATE_SMACS, "EZSP_CALCULATE_SMACS" }, { EZSP_CALCULATE_SMACS_HANDLER, "EZSP_CALCULATE_SMACS_HANDLER" }, + { EZSP_GENERATE_CBKE_KEYS283K1, "EZSP_GENERATE_CBKE_KEYS283K1" }, + { EZSP_GENERATE_CBKE_KEYS_HANDLER283K1, "EZSP_GENERATE_CBKE_KEYS_HANDLER283K1" }, + { EZSP_CALCULATE_SMACS283K1, "EZSP_CALCULATE_SMACS283K1" }, + { EZSP_CALCULATE_SMACS_HANDLER283K1, "EZSP_CALCULATE_SMACS_HANDLER283K1" }, + { EZSP_CLEAR_TEMPORARY_DATA_MAYBE_STORE_LINK_KEY, "EZSP_CLEAR_TEMPORARY_DATA_MAYBE_STORE_LINK_KEY" }, + { EZSP_CLEAR_TEMPORARY_DATA_MAYBE_STORE_LINK_KEY283K1, "EZSP_CLEAR_TEMPORARY_DATA_MAYBE_STORE_LINK_KEY283K1" }, + { EZSP_GET_CERTIFICATE, "EZSP_GET_CERTIFICATE" }, + { EZSP_GET_CERTIFICATE283K1, "EZSP_GET_CERTIFICATE283K1" }, + { EZSP_DSA_SIGN, "EZSP_DSA_SIGN" }, { EZSP_DSA_SIGN_HANDLER, "EZSP_DSA_SIGN_HANDLER" }, + { EZSP_DSA_VERIFY, "EZSP_DSA_VERIFY" }, { EZSP_DSA_VERIFY_HANDLER, "EZSP_DSA_VERIFY_HANDLER" }, + { EZSP_DSA_VERIFY283K1, "EZSP_DSA_VERIFY283K1" }, + { EZSP_SET_PREINSTALLED_CBKE_DATA, "EZSP_SET_PREINSTALLED_CBKE_DATA" }, + { EZSP_SAVE_PREINSTALLED_CBKE_DATA283K1, "EZSP_SAVE_PREINSTALLED_CBKE_DATA283K1" }, + /* Mfglib */ { EZSP_MFGLIB_RX_HANDLER, "EZSP_MFGLIB_RX_HANDLER" }, + /* --- */ + /* Bootloader */ + { EZSP_LAUNCH_STANDALONE_BOOTLOADER, "EZSP_LAUNCH_STANDALONE_BOOTLOADER" }, + { EZSP_SEND_BOOTLOAD_MESSAGE, "EZSP_SEND_BOOTLOAD_MESSAGE" }, + { EZSP_GET_STANDALONE_BOOTLOADER_VERSION_PLAT_MICRO_PHY, "EZSP_GET_STANDALONE_BOOTLOADER_VERSION_PLAT_MICRO_PHY" }, { EZSP_INCOMING_BOOTLOAD_MESSAGE_HANDLER, "EZSP_INCOMING_BOOTLOAD_MESSAGE_HANDLER" }, { EZSP_BOOTLOAD_TRANSMIT_COMPLETE_HANDLER, "EZSP_BOOTLOAD_TRANSMIT_COMPLETE_HANDLER" }, + { EZSP_AES_ENCRYPT, "EZSP_AES_ENCRYPT" }, + { EZSP_OVERRIDE_CURRENT_CHANNEL, "EZSP_OVERRIDE_CURRENT_CHANNEL" }, + /* ZLL */ + /* --- */ + /* WWAH */ + /* --- */ + /* Green Power */ + { EZSP_GP_PROXY_TABLE_PROCESS_GP_PAIRING, "EZSP_GP_PROXY_TABLE_PROCESS_GP_PAIRING" }, + { EZSP_D_GP_SEND, "EZSP_D_GP_SEND" }, + { EZSP_D_GP_SENT_HANDLER, "EZSP_D_GP_SENT_HANDLER" }, + { EZSP_GPEP_INCOMING_MESSAGE_HANDLER, "EZSP_GPEP_INCOMING_MESSAGE_HANDLER" }, + { EZSP_GP_PROXY_TABLE_GET_ENTRY, "EZSP_GP_PROXY_TABLE_GET_ENTRY" }, + { EZSP_GP_PROXY_TABLE_LOOKUP, "EZSP_GP_PROXY_TABLE_LOOKUP" }, + { EZSP_GP_SINK_TABLE_GET_ENTRY, "EZSP_GP_SINK_TABLE_GET_ENTRY" }, + { EZSP_GP_SINK_TABLE_LOOKUP, "EZSP_GP_SINK_TABLE_LOOKUP" }, + { EZSP_GP_SINK_TABLE_SET_ENTRY, "EZSP_GP_SINK_TABLE_SET_ENTRY" }, + { EZSP_GP_SINK_TABLE_REMOVE_ENTRY, "EZSP_GP_SINK_TABLE_REMOVE_ENTRY" }, + { EZSP_GP_SINK_TABLE_FIND_OR_ALLOCATE_ENTRY, "EZSP_GP_SINK_TABLE_FIND_OR_ALLOCATE_ENTRY" }, + { EZSP_GP_SINK_TABLE_CLEAR_ALL, "EZSP_GP_SINK_TABLE_CLEAR_ALL" }, + { EZSP_GP_SINK_TABLE_INIT, "EZSP_GP_SINK_TABLE_INIT" }, + /* Secure EZSP */ + /* --- */ }; auto it = MyEnumStrings.find(in); return it == MyEnumStrings.end() ? "OUT_OF_RANGE" : it->second; diff --git a/src/domain/zbmessage/zclheader.h b/src/domain/zbmessage/zclheader.h index d8c5e05e..179e1eb3 100644 --- a/src/domain/zbmessage/zclheader.h +++ b/src/domain/zbmessage/zclheader.h @@ -16,8 +16,14 @@ #include #endif // USE_RARITAN +// manufacturer code +#define PUBLIC_CODE 0xFFFF #define LG_MAN_CODE 0x1021 +// profile +#define GP_PROFILE_ID 0xA1E0 + + class CZCLHeader; /* Forward declaration */ void swap(CZCLHeader& first, CZCLHeader& second); /* Declaration before qualifying ::swap() as friend for class CZCLHeader */ diff --git a/src/domain/zbmessage/zigbee-message.h b/src/domain/zbmessage/zigbee-message.h index c8432f0f..65b73b57 100644 --- a/src/domain/zbmessage/zigbee-message.h +++ b/src/domain/zbmessage/zigbee-message.h @@ -179,9 +179,10 @@ class CZigBeeMsg */ std::vector Get( void ) const; -private: +/*-- TEST GREEN POWER */ /** APS */ CAPSFrame aps; +private: /** ZCL Header */ CZCLHeader zcl_header; diff --git a/src/domain/zigbee-tools/green-power-sink.cpp b/src/domain/zigbee-tools/green-power-sink.cpp index 87520426..ef247e71 100644 --- a/src/domain/zigbee-tools/green-power-sink.cpp +++ b/src/domain/zigbee-tools/green-power-sink.cpp @@ -11,19 +11,44 @@ #include "green-power-sink.h" #include "../ezsp-protocol/struct/ember-gp-address-struct.h" +#include "../../domain/zbmessage/zigbee-message.h" + #include "../../spi/GenericLogger.h" #include "../../spi/ILogger.h" +// some defines to help understanding +#define GP_ENDPOINT 242 + +// cluster +#define GP_CLUSTER_ID 0x0021 +// receive client command +#define GP_PROXY_COMMISIONING_MODE_CLIENT_CMD_ID 0x02 + + -CGpSink::CGpSink( CEzspDongle &i_dongle ) : +CGpSink::CGpSink( CEzspDongle &i_dongle, CZigbeeMessaging &i_zb_messaging ) : dongle(i_dongle), + zb_messaging(i_zb_messaging), sink_table(), observers() { dongle.registerObserver(this); } +void CGpSink::init(void) +{ + // initialize green power sink + clogD << "Call EZSP_GP_SINK_TABLE_INIT" << std::endl; + dongle.sendCommand(EZSP_GP_SINK_TABLE_INIT); +} + +void CGpSink::openCommissioningSession(void) +{ + // set local proxy in commissioning mode + sendLocalGPProxyCommissioningMode(); +} + uint8_t CGpSink::registerGpd( uint32_t i_source_id ) { CGpSinkTableEntry l_entry = CGpSinkTableEntry(i_source_id); @@ -39,6 +64,11 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re { switch( i_cmd ) { + case EZSP_GP_SINK_TABLE_INIT: + { + clogI << "EZSP_GP_SINK_TABLE_INIT RSP" << std::endl; + } + break; case EZSP_GPEP_INCOMING_MESSAGE_HANDLER: { EEmberStatus l_status = static_cast(i_msg_receive.at(0)); @@ -122,3 +152,44 @@ void CGpSink::notifyObserversOfRxGpFrame( CGpFrame i_gpf ) { observer->handleRxGpFrame( i_gpf ); } } + +void CGpSink::sendLocalGPProxyCommissioningMode(void) +{ + // forge GP Proxy Commissioning Mode command + // assume we are coordinator of network and our nodeId is 0 + + CZigBeeMsg l_gp_comm_msg; + std::vector l_gp_comm_payload; + + // options: + // bit0 (Action) : 0b1 / request to enter commissioning mode + // bit1-3 (exit mode) : 0b010 / On first Pairing success + // bit4 (channel present) : 0b0 / shall always be set to 0 according current spec. + // bit5 (unicast communication) : 0b0 / send GP Commissioning Notification commands in broadcast + // bit6-7 (reserved) + l_gp_comm_payload.push_back(0x05); + + // comm windows 2 bytes + // present only if exit mode flag On commissioning Window expiration (bit0) is set + /* + l_gp_comm_payload.push_back(u16_get_lo_u8(180)); + l_gp_comm_payload.push_back(u16_get_hi_u8(180)); + */ + // channel + // never present with current specification + /* + l_gp_comm_payload.push_back(0); + */ + + // create message sending from ep242 to ep242 using green power profile + l_gp_comm_msg.SetSpecific(GP_PROFILE_ID, PUBLIC_CODE, GP_ENDPOINT, + GP_CLUSTER_ID, GP_PROXY_COMMISIONING_MODE_CLIENT_CMD_ID, + E_DIR_SERVER_TO_CLIENT, l_gp_comm_payload, 0, 0, 0); + + // WARNING use ep 242 as sources + l_gp_comm_msg.aps.src_ep = GP_ENDPOINT; + + // + clogI << "SEND UNICAST : OPEN GP COMMISSIONING\n"; + zb_messaging.SendUnicast(0,l_gp_comm_msg); +} \ No newline at end of file diff --git a/src/domain/zigbee-tools/green-power-sink.h b/src/domain/zigbee-tools/green-power-sink.h index a1a1f10b..159e22f1 100644 --- a/src/domain/zigbee-tools/green-power-sink.h +++ b/src/domain/zigbee-tools/green-power-sink.h @@ -7,6 +7,7 @@ #include "../zbmessage/green-power-frame.h" #include "../green-power-observer.h" #include "../ezsp-dongle.h" +#include "zigbee-messaging.h" #include "green-power-sink-table.h" #ifdef USE_RARITAN @@ -18,13 +19,23 @@ class CGpSink : public CEzspDongleObserver { public: - CGpSink( CEzspDongle &i_dongle ); + CGpSink( CEzspDongle &i_dongle, CZigbeeMessaging &i_zb_messaging ); CGpSink() = delete; /* Construction without arguments is not allowed */ CGpSink(const CGpSink&) = delete; /* No copy construction allowed */ CGpSink& operator=(CGpSink) = delete; /* No assignment allowed */ + /** + * @brief Initialize sink, shall be done after a network init. + */ + void init(void); + + /** + * @brief Open a commissioning session for limited time, close as soon as a binding is done. + */ + void openCommissioningSession(void); + /** * @brief add a green power sink table entry * @@ -47,6 +58,7 @@ class CGpSink : public CEzspDongleObserver private: CEzspDongle &dongle; + CZigbeeMessaging &zb_messaging; CGpSinkTable sink_table; /** @@ -54,6 +66,14 @@ class CGpSink : public CEzspDongleObserver */ std::set observers; void notifyObserversOfRxGpFrame( CGpFrame i_gpf ); + + + /** + * @brief send zigbee unicast message GP Proxy Commissioning Mode. + * done from sink to local dongle. + * WARNING all parameters are hardcoded for testing + */ + void sendLocalGPProxyCommissioningMode(void); }; #ifdef USE_RARITAN diff --git a/src/example/CAppDemo.cpp b/src/example/CAppDemo.cpp index b6d05add..e488e0fd 100644 --- a/src/example/CAppDemo.cpp +++ b/src/example/CAppDemo.cpp @@ -21,7 +21,7 @@ CAppDemo::CAppDemo(IUartDriver& uartDriver, ITimerFactory &i_timer_factory, bool dongle(i_timer_factory, this), zb_messaging(dongle, i_timer_factory), zb_nwk(dongle, zb_messaging), - gp_sink(dongle), + gp_sink(dongle, zb_messaging), app_state(APP_NOT_INIT), db(), ezsp_version(6), @@ -266,6 +266,13 @@ void CAppDemo::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_r { setAppState(APP_READY); + // init gp sink + gp_sink.init(); + + // for demo immediately open commissioning session + gp_sink.openCommissioningSession(); + + /*-- test gREEN poWER only // we open network, so we can enter new devices zb_nwk.OpenNetwork( 60 ); @@ -298,6 +305,7 @@ void CAppDemo::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_r zb_messaging.SendZDOCommand( i_id, ZDP_ACTIVE_EP, payload ); } }); + */ } else { diff --git a/src/example/mainEzspTest.cpp b/src/example/mainEzspTest.cpp index bbd62a44..a6e581d4 100644 --- a/src/example/mainEzspTest.cpp +++ b/src/example/mainEzspTest.cpp @@ -43,7 +43,7 @@ int main(int argc, char **argv) { SerialUartDriver uartDriver; CppThreadsTimerFactory timerFactory; - ConsoleLogger::getInstance().setLogLevel(LOG_LEVEL::INFO); /* Only display logs for debug level info and higher (up to error) */ + ConsoleLogger::getInstance().setLogLevel(LOG_LEVEL::TRACE); /* Only display logs for debug level info and higher (up to error) */ #endif #ifdef USE_RARITAN RaritanEventLoop eventLoop; From e43e91dd8977a7f6b530a6f2d8a9b950ca2d660a Mon Sep 17 00:00:00 2001 From: seb Date: Fri, 8 Nov 2019 14:57:46 +0100 Subject: [PATCH 02/44] authorize empty constructor and assignement operator --- src/domain/zbmessage/green-power-frame.cpp | 15 +++++++++++++++ src/domain/zbmessage/green-power-frame.h | 4 ++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/domain/zbmessage/green-power-frame.cpp b/src/domain/zbmessage/green-power-frame.cpp index b2710319..3de49f75 100644 --- a/src/domain/zbmessage/green-power-frame.cpp +++ b/src/domain/zbmessage/green-power-frame.cpp @@ -12,6 +12,21 @@ #include "../ezsp-protocol/struct/ember-gp-address-struct.h" +CGpFrame::CGpFrame(): + link_value(0), + sequence_number(0), + source_id(0), + security(GPD_NO_SECURITY), + key_type(GPD_KEY_TYPE_NO_KEY), + auto_commissioning(false), + rx_after_tx(false), + security_frame_counter(0), + command_id(0xFF), + mic(0), + proxy_table_entry(0xFF), + payload() +{ +} CGpFrame::CGpFrame(const std::vector& raw_message): link_value(0), diff --git a/src/domain/zbmessage/green-power-frame.h b/src/domain/zbmessage/green-power-frame.h index c8e8bcae..1410b9b8 100644 --- a/src/domain/zbmessage/green-power-frame.h +++ b/src/domain/zbmessage/green-power-frame.h @@ -33,14 +33,14 @@ class CGpFrame * * Construction without arguments is not allowed */ - CGpFrame() = delete; + CGpFrame(); // = delete; /** * @brief Assignment operator * * Copy construction is forbidden on this class */ - CGpFrame& operator=(const CGpFrame& other) = delete; + //CGpFrame& operator=(const CGpFrame& other) = delete; /** * @brief Construction from an incoming ezsp raw message From 77296de9af2283ec2a14b62845744d6ee65c2872 Mon Sep 17 00:00:00 2001 From: seb Date: Fri, 8 Nov 2019 14:58:29 +0100 Subject: [PATCH 03/44] adding new structure, not used for now --- .../ember-gp-sink-table-entry-struct.cpp | 17 ++++++ .../struct/ember-gp-sink-table-entry-struct.h | 55 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp create mode 100644 src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp new file mode 100644 index 00000000..3cd7ad9a --- /dev/null +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp @@ -0,0 +1,17 @@ +/** + * @file ember-g-sink-table-entry-struct.cpp + * + * @brief The internal representation of a sink table entry. + */ + +#include +#include + +#include "ember-gp-sink-table-entry-struct.h" + +#include "../../byte-manip.h" + +CEmberGpSinkTableEntryStruct::CEmberGpSinkTableEntryStruct(const std::vector& raw_message) +{ + +} \ No newline at end of file diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h new file mode 100644 index 00000000..66f98c8f --- /dev/null +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h @@ -0,0 +1,55 @@ +/** + * @file ember-gp-sink-table-entry-struct.h + * + * @brief The internal representation of a sink table entry. + */ + +#pragma once + +#include "../ezsp-enum.h" + +#ifdef USE_RARITAN +/**** Start of the official API; no includes below this point! ***************/ +#include +#endif // USE_RARITAN + +class CEmberGpSinkTableEntryStruct +{ + public: + /** + * @brief Default constructor + * + * Construction without arguments is not allowed + */ + CEmberGpSinkTableEntryStruct() = delete; + + /** + * @brief Construction from a buffer + * + * @param raw_message The buffer to construct from + */ + CEmberGpSinkTableEntryStruct(const std::vector& raw_message); + + /** + * @brief Copy constructor + * + * Copy construction is forbidden on this class + */ + CEmberGpSinkTableEntryStruct(const CEmberGpSinkTableEntryStruct& other) = delete; + + /** + * @brief Assignment operator + * + * Assignment is forbidden on this class + */ + CEmberGpSinkTableEntryStruct& operator=(const CEmberGpSinkTableEntryStruct& other) = delete; + + private: + + + +}; + +#ifdef USE_RARITAN +#include +#endif // USE_RARITAN \ No newline at end of file From 860383966e5c74fd8db7f392fb71fc74e160d6ba Mon Sep 17 00:00:00 2001 From: seb Date: Fri, 8 Nov 2019 14:59:16 +0100 Subject: [PATCH 04/44] adding new function. MANUAL GPD COMMISSIONING WORK WITH SOME PARAMTER HARDCODED --- src/domain/zigbee-tools/green-power-sink.cpp | 518 ++++++++++++++++++- src/domain/zigbee-tools/green-power-sink.h | 33 ++ 2 files changed, 543 insertions(+), 8 deletions(-) diff --git a/src/domain/zigbee-tools/green-power-sink.cpp b/src/domain/zigbee-tools/green-power-sink.cpp index ef247e71..5a94f21b 100644 --- a/src/domain/zigbee-tools/green-power-sink.cpp +++ b/src/domain/zigbee-tools/green-power-sink.cpp @@ -24,6 +24,35 @@ // receive client command #define GP_PROXY_COMMISIONING_MODE_CLIENT_CMD_ID 0x02 +// GPF Command +#define GPF_SCENE_0_CMD 0x10 +#define GPF_SCENE_1_CMD 0x11 +#define GPF_SCENE_2_CMD 0x12 +#define GPF_SCENE_3_CMD 0x13 +#define GPF_SCENE_4_CMD 0x14 +#define GPF_SCENE_5_CMD 0x15 +#define GPF_SCENE_6_CMD 0x16 +#define GPF_SCENE_7_CMD 0x17 + +#define GPF_STORE_SCENE_0_CMD 0x18 +#define GPF_STORE_SCENE_1_CMD 0x19 +#define GPF_STORE_SCENE_2_CMD 0x1A +#define GPF_STORE_SCENE_3_CMD 0x1B +#define GPF_STORE_SCENE_4_CMD 0x1C +#define GPF_STORE_SCENE_5_CMD 0x1D +#define GPF_STORE_SCENE_6_CMD 0x1E +#define GPF_STORE_SCENE_7_CMD 0x1F + +#define GPF_OFF_CMD 0x20 +#define GPF_ON_CMD 0x21 +#define GPF_TOGGLE_CMD 0x22 + +#define GPF_UP_W_ON_OFF_CMD 0x34 +#define GPF_STOP_CMD 0x35 +#define GPF_DOWN_W_ON_OFF_CMD 0x36 + +#define GPF_COMMISSIONING_CMD 0xE0 +#define GPF_DECOMMISSIONING_CMD 0xE1 @@ -31,6 +60,8 @@ CGpSink::CGpSink( CEzspDongle &i_dongle, CZigbeeMessaging &i_zb_messaging ) : dongle(i_dongle), zb_messaging(i_zb_messaging), sink_table(), + sink_state(SINK_NOT_INIT), + gpf_comm_frame(), observers() { dongle.registerObserver(this); @@ -41,12 +72,18 @@ void CGpSink::init(void) // initialize green power sink clogD << "Call EZSP_GP_SINK_TABLE_INIT" << std::endl; dongle.sendCommand(EZSP_GP_SINK_TABLE_INIT); + + // set state + setSinkState(SINK_READY); } void CGpSink::openCommissioningSession(void) { // set local proxy in commissioning mode sendLocalGPProxyCommissioningMode(); + + // set state + setSinkState(SINK_COM_OPEN); } uint8_t CGpSink::registerGpd( uint32_t i_source_id ) @@ -108,6 +145,19 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re { // to test notify notifyObserversOfRxGpFrame( gpf ); + + // if we are in Commissioning and this is a commissioning frame : use it ! + if( (SINK_COM_OPEN == sink_state) && (GPF_COMMISSIONING_CMD == gpf.getCommandId()) ) + { + // find entry in sink table + gpSinkTableFindOrAllocateEntry(gpf.getSourceId()); + + // save incomming message + gpf_comm_frame = gpf; + + // set new state + setSinkState(SINK_COM_IN_PROGRESS); + } } else { @@ -122,6 +172,189 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re } break; + case EZSP_GP_SINK_TABLE_FIND_OR_ALLOCATE_ENTRY: + { + if( SINK_COM_IN_PROGRESS == sink_state ) + { + // retrieve entry + gpSinkGetEntry( i_msg_receive.at(0) ); + } + } + break; + + case EZSP_GP_SINK_TABLE_GET_ENTRY: + { + if( SINK_COM_IN_PROGRESS == sink_state ) + { + // set the entry with new parameters + std::vector l_struct; + uint32_t l_src_id = gpf_comm_frame.getSourceId(); + // Internal status of the sink table entry. + l_struct.push_back(0x01); // active, 0xff : disable + // The tunneling options (this contains both options and extendedOptions from the spec). WARNING 16 bits !!! + l_struct.push_back(0xA8); + l_struct.push_back(0x02); + // The addressing info of the GPD. + l_struct.push_back(0x00); // short address + l_struct.push_back(static_cast(l_src_id&0xFF)); + l_struct.push_back(static_cast((l_src_id>>8)&0xFF)); + l_struct.push_back(static_cast((l_src_id>>16)&0xFF)); + l_struct.push_back(static_cast((l_src_id>>24)&0xFF)); + l_struct.push_back(static_cast(l_src_id&0xFF)); + l_struct.push_back(static_cast((l_src_id>>8)&0xFF)); + l_struct.push_back(static_cast((l_src_id>>16)&0xFF)); + l_struct.push_back(static_cast((l_src_id>>24)&0xFF)); + l_struct.push_back(0x00); // endpoint -> not used + // The device id for the GPD. + l_struct.push_back(gpf_comm_frame.getPayload().at(0)); // 0x02 + // The list of sinks (hardcoded to 2 which is the spec minimum). + l_struct.push_back(0xFF); // unused + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0xFF); // unused + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + // The assigned alias for the GPD. + l_struct.push_back(static_cast(l_src_id&0xFF)); + l_struct.push_back(static_cast((l_src_id>>8)&0xFF)); + + // The groupcast radius. + l_struct.push_back(0x00); + + // The security options field. + l_struct.push_back(0x12); + + // The security frame counter of the GPD. + l_struct.push_back(gpf_comm_frame.getPayload().at(23)); + l_struct.push_back(gpf_comm_frame.getPayload().at(24)); + l_struct.push_back(gpf_comm_frame.getPayload().at(25)); + l_struct.push_back(gpf_comm_frame.getPayload().at(26)); + + // The key to use for GPD. 59 13 29 50 28 9D 14 FD 73 F9 C3 25 D4 57 AB B5 + l_struct.push_back(0x59); + l_struct.push_back(0x13); + l_struct.push_back(0x29); + l_struct.push_back(0x50); + l_struct.push_back(0x28); + l_struct.push_back(0x9D); + l_struct.push_back(0x14); + l_struct.push_back(0xFD); + l_struct.push_back(0x73); + l_struct.push_back(0xF9); + l_struct.push_back(0xC3); + l_struct.push_back(0x25); + l_struct.push_back(0xD4); + l_struct.push_back(0x57); + l_struct.push_back(0xAB); + l_struct.push_back(0xB5); + // call + gpSinkSetEntry(0,l_struct); + + } + } + break; + + case EZSP_GP_SINK_TABLE_SET_ENTRY: + { + if( SINK_COM_IN_PROGRESS == sink_state ) + { + // do proxy pairing + std::vector l_struct; + uint32_t l_src_id = gpf_comm_frame.getSourceId(); + // The options field of the GP Pairing command + l_struct.push_back(0xA8); + l_struct.push_back(0xE5); + l_struct.push_back(0x02); + l_struct.push_back(0x00); + // The addressing info of the target GPD. + l_struct.push_back(0x00); // short address + l_struct.push_back(static_cast(l_src_id&0xFF)); + l_struct.push_back(static_cast((l_src_id>>8)&0xFF)); + l_struct.push_back(static_cast((l_src_id>>16)&0xFF)); + l_struct.push_back(static_cast((l_src_id>>24)&0xFF)); + l_struct.push_back(static_cast(l_src_id&0xFF)); + l_struct.push_back(static_cast((l_src_id>>8)&0xFF)); + l_struct.push_back(static_cast((l_src_id>>16)&0xFF)); + l_struct.push_back(static_cast((l_src_id>>24)&0xFF)); + l_struct.push_back(0x00); // endpoint -> not used + // The communication mode of the GP Sink. + l_struct.push_back(0x01); + // The network address of the GP Sink. + l_struct.push_back(0xFF); + l_struct.push_back(0xFF); + // The group ID of the GP Sink. + l_struct.push_back(l_src_id&0xFF); + l_struct.push_back((l_src_id>>8)&0xFF); + // The alias assigned to the GPD. + l_struct.push_back(0xFF); + l_struct.push_back(0xFF); + // The IEEE address of the GP Sink. + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + // The key to use for GPD. 59 13 29 50 28 9D 14 FD 73 F9 C3 25 D4 57 AB B5 + l_struct.push_back(0x59); + l_struct.push_back(0x13); + l_struct.push_back(0x29); + l_struct.push_back(0x50); + l_struct.push_back(0x28); + l_struct.push_back(0x9D); + l_struct.push_back(0x14); + l_struct.push_back(0xFD); + l_struct.push_back(0x73); + l_struct.push_back(0xF9); + l_struct.push_back(0xC3); + l_struct.push_back(0x25); + l_struct.push_back(0xD4); + l_struct.push_back(0x57); + l_struct.push_back(0xAB); + l_struct.push_back(0xB5); + // The security frame counter of the GPD. + l_struct.push_back(gpf_comm_frame.getPayload().at(23)); + l_struct.push_back(gpf_comm_frame.getPayload().at(24)); + l_struct.push_back(gpf_comm_frame.getPayload().at(25)); + l_struct.push_back(gpf_comm_frame.getPayload().at(26)); + // The forwarding radius. + l_struct.push_back(0x00); + // call + gpProxyTableProcessGpPairing(l_struct); + } + } + break; + + case EZSP_GP_PROXY_TABLE_PROCESS_GP_PAIRING: + { + if( SINK_COM_IN_PROGRESS == sink_state ) + { + clogI << "CGpSink::ezspHandler EZSP_GP_PROXY_TABLE_PROCESS_GP_PAIRING gpPairingAdded : " << std::hex << std::setw(2) << std::setfill('0') << static_cast(i_msg_receive[0]) << std::endl; + + // set new state + setSinkState(SINK_READY); + } + } + break; + default: { /* DEBUG VIEW @@ -171,15 +404,10 @@ void CGpSink::sendLocalGPProxyCommissioningMode(void) // comm windows 2 bytes // present only if exit mode flag On commissioning Window expiration (bit0) is set - /* - l_gp_comm_payload.push_back(u16_get_lo_u8(180)); - l_gp_comm_payload.push_back(u16_get_hi_u8(180)); - */ - // channel + + // channel 1 byte // never present with current specification - /* - l_gp_comm_payload.push_back(0); - */ + // create message sending from ep242 to ep242 using green power profile l_gp_comm_msg.SetSpecific(GP_PROFILE_ID, PUBLIC_CODE, GP_ENDPOINT, @@ -192,4 +420,278 @@ void CGpSink::sendLocalGPProxyCommissioningMode(void) // clogI << "SEND UNICAST : OPEN GP COMMISSIONING\n"; zb_messaging.SendUnicast(0,l_gp_comm_msg); +} + +/* +void CGpSink::gpCloseCommissioning() +{ + std::vector l_payload; + + // The action to perform on the GP TX queue (true to add, false to remove). + l_payload.push_back(0x00); + + // Whether to use ClearChannelAssessment when transmitting the GPDF. + l_payload.push_back(0x00); + + // The Address of the destination GPD. + l_payload.push_back(0x00); + l_payload.push_back(0xFF); + l_payload.push_back(0xFF); + l_payload.push_back(0xFF); + l_payload.push_back(0xFF); + l_payload.push_back(0xFF); + l_payload.push_back(0xFF); + l_payload.push_back(0xFF); + l_payload.push_back(0xFF); + l_payload.push_back(0x7F); + + // The GPD command ID to send. + l_payload.push_back(0x00); + + // The length of the GP command payload. + l_payload.push_back(0x01); + + // The GP command payload. + l_payload.push_back(0x00); + + // The handle to refer to the GPDF. + l_payload.push_back(0x00); + + // How long to keep the GPDF in the TX Queue. + l_payload.push_back(0x00); + + clogI << "EZSP_D_GP_SEND : CLOSE GP COMMISSIONING\n"; + dongle.sendCommand(EZSP_D_GP_SEND,l_payload); +} +*/ + +/* +void CGpSink::gpBrCommissioningNotification( uint32_t i_gpd_src_id, uint8_t i_seq_number ) +{ + std::vector l_proxy_br_payload; + + // The source from which to send the broadcast + l_proxy_br_payload.push_back(static_cast(i_gpd_src_id&0xFF)); + l_proxy_br_payload.push_back(static_cast((i_gpd_src_id>>8)&0xFF)); + + // The destination to which to send the broadcast. This must be one of the three ZigBee broadcast addresses. + l_proxy_br_payload.push_back(0xFD); + l_proxy_br_payload.push_back(0xFF); + + // The network sequence number for the broadcast + l_proxy_br_payload.push_back(i_seq_number); + + // The APS frame for the message. + CAPSFrame l_aps; + l_aps.SetDefaultAPS(GP_PROFILE_ID,GP_CLUSTER_ID,GP_ENDPOINT); + l_aps.src_ep = GP_ENDPOINT; + std::vector l_ember_aps = l_aps.GetEmberAPS(); + l_proxy_br_payload.insert(l_proxy_br_payload.end(), l_ember_aps.begin(), l_ember_aps.end()); + + // The message will be delivered to all nodes within radius hops of the sender. A radius of zero is converted to EMBER_MAX_HOPS. + l_proxy_br_payload.push_back(0x00); + + // A value chosen by the Host. This value is used in the ezspMessageSentHandler response to refer to this message. + l_proxy_br_payload.push_back(0x00); + + // The length of the messageContents parameter in bytes. + l_proxy_br_payload.push_back(49); + + // The broadcast message. + l_proxy_br_payload.push_back(0x11); + l_proxy_br_payload.push_back(0x06); + l_proxy_br_payload.push_back(0x04); + l_proxy_br_payload.push_back(0x00); + l_proxy_br_payload.push_back(0x08); + l_proxy_br_payload.push_back(0x50); + l_proxy_br_payload.push_back(0x00); + l_proxy_br_payload.push_back(0x51); + l_proxy_br_payload.push_back(0x00); + l_proxy_br_payload.push_back(0x24); + l_proxy_br_payload.push_back(0x00); + l_proxy_br_payload.push_back(0x00); + l_proxy_br_payload.push_back(0x00); + l_proxy_br_payload.push_back(0xe0); + l_proxy_br_payload.push_back(0x1f); + l_proxy_br_payload.push_back(0x02); + l_proxy_br_payload.push_back(0xc5); + l_proxy_br_payload.push_back(0xf2); + l_proxy_br_payload.push_back(0xa8); + l_proxy_br_payload.push_back(0xac); + l_proxy_br_payload.push_back(0x43); + l_proxy_br_payload.push_back(0x76); + l_proxy_br_payload.push_back(0x30); + l_proxy_br_payload.push_back(0x80); + l_proxy_br_payload.push_back(0x89); + l_proxy_br_payload.push_back(0x5f); + l_proxy_br_payload.push_back(0x3c); + l_proxy_br_payload.push_back(0xd5); + l_proxy_br_payload.push_back(0xdc); + l_proxy_br_payload.push_back(0x9a); + l_proxy_br_payload.push_back(0xd8); + l_proxy_br_payload.push_back(0x87); + l_proxy_br_payload.push_back(0x1c); + l_proxy_br_payload.push_back(0x0d); + l_proxy_br_payload.push_back(0x15); + l_proxy_br_payload.push_back(0xde); + l_proxy_br_payload.push_back(0x17); + l_proxy_br_payload.push_back(0x2b); + l_proxy_br_payload.push_back(0x24); + l_proxy_br_payload.push_back(0x00); + l_proxy_br_payload.push_back(0x00); + l_proxy_br_payload.push_back(0x00); + l_proxy_br_payload.push_back(0x04); + l_proxy_br_payload.push_back(0x02); + l_proxy_br_payload.push_back(0x20); + l_proxy_br_payload.push_back(0x21); + l_proxy_br_payload.push_back(0x00); + l_proxy_br_payload.push_back(0x00); + l_proxy_br_payload.push_back(0xdc); + + clogI << "EZSP_PROXY_BROADCAST\n"; + dongle.sendCommand(EZSP_PROXY_BROADCAST,l_proxy_br_payload); +} +*/ +/* +void CAppDemo::ezspGetExtendedValue( uint8_t i_value_id, uint32_t i_characteristic ) +{ + std::vector l_payload; + + // Identifies which extended value ID to read. + l_payload.push_back(i_value_id); + + // Identifies which characteristics of the extended value ID to read. These are specific to the value being read. + l_payload.push_back((uint8_t)(i_characteristic&0xFF)); + l_payload.push_back((uint8_t)((i_characteristic>>8)&0xFF)); + l_payload.push_back((uint8_t)((i_characteristic>>16)&0xFF)); + l_payload.push_back((uint8_t)((i_characteristic>>24)&0xFF)); + + clogI << "EZSP_GET_EXTENDED_VALUE\n"; + dongle.sendCommand(EZSP_GET_EXTENDED_VALUE,l_payload); +} +*/ + +/* +void CAppDemo::gpSinkTableLookup( uint32_t i_src_id ) +{ + std::vector l_payload; + + // EmberGpAddress addr The address to search for. + l_payload.push_back(0x00); + l_payload.push_back((uint8_t)(i_src_id&0xFF)); + l_payload.push_back((uint8_t)((i_src_id>>8)&0xFF)); + l_payload.push_back((uint8_t)((i_src_id>>16)&0xFF)); + l_payload.push_back((uint8_t)((i_src_id>>24)&0xFF)); + l_payload.push_back((uint8_t)(i_src_id&0xFF)); + l_payload.push_back((uint8_t)((i_src_id>>8)&0xFF)); + l_payload.push_back((uint8_t)((i_src_id>>16)&0xFF)); + l_payload.push_back((uint8_t)((i_src_id>>24)&0xFF)); + l_payload.push_back(0x00); + + clogI << "EZSP_GP_SINK_TABLE_LOOKUP\n"; + dongle.sendCommand(EZSP_GP_SINK_TABLE_LOOKUP,l_payload); +} +*/ + +/** + * Finds or allocates a sink entry + */ +void CGpSink::gpSinkTableFindOrAllocateEntry( uint32_t i_src_id ) +{ + std::vector l_payload; + + // An EmberGpAddress struct containing a copy of the gpd address to be found. + l_payload.push_back(0x00); + l_payload.push_back((uint8_t)(i_src_id&0xFF)); + l_payload.push_back((uint8_t)((i_src_id>>8)&0xFF)); + l_payload.push_back((uint8_t)((i_src_id>>16)&0xFF)); + l_payload.push_back((uint8_t)((i_src_id>>24)&0xFF)); + l_payload.push_back((uint8_t)(i_src_id&0xFF)); + l_payload.push_back((uint8_t)((i_src_id>>8)&0xFF)); + l_payload.push_back((uint8_t)((i_src_id>>16)&0xFF)); + l_payload.push_back((uint8_t)((i_src_id>>24)&0xFF)); + l_payload.push_back(0x00); + + dongle.sendCommand(EZSP_GP_SINK_TABLE_FIND_OR_ALLOCATE_ENTRY,l_payload); +} + +/** + * Retrieves the sink table entry stored at the passed index. + */ +void CGpSink::gpSinkGetEntry( uint8_t i_index ) +{ + std::vector l_payload; + + // The index of the requested sink table entry. + l_payload.push_back(i_index); + + clogI << "EZSP_GP_SINK_TABLE_GET_ENTRY\n"; + dongle.sendCommand(EZSP_GP_SINK_TABLE_GET_ENTRY,l_payload); +} + + +/** + * Retrieves the sink table entry stored at the passed index. + */ +void CGpSink::gpSinkSetEntry( uint8_t i_index, std::vector i_struct ) +{ + std::vector l_payload; + + // The index of the requested sink table entry. + l_payload.push_back(i_index); + + // struct + l_payload.insert(l_payload.end(), i_struct.begin(), i_struct.end()); + + clogI << "EZSP_GP_SINK_TABLE_SET_ENTRY\n"; + dongle.sendCommand(EZSP_GP_SINK_TABLE_SET_ENTRY,l_payload); +} + + +/** + * Update the GP Proxy table based on a GP pairing. + */ +void CGpSink::gpProxyTableProcessGpPairing( std::vector i_param ) +{ + std::vector l_payload; + + // \todo used seperate paramter or a dedicated struct class + l_payload.insert(l_payload.end(), i_param.begin(), i_param.end()); + + clogI << "EZSP_GP_PROXY_TABLE_PROCESS_GP_PAIRING\n"; + dongle.sendCommand(EZSP_GP_PROXY_TABLE_PROCESS_GP_PAIRING,l_payload); +} + + +/** + * Clear all GP tables + */ +/* +void CAppDemo::gpClearAllTables( void ) +{ + // sink table + dongle.sendCommand(EZSP_GP_SINK_TABLE_CLEAR_ALL); +} +*/ + + + +/** + * utility function can managed error state + */ +void CGpSink::setSinkState( ESinkState i_state ) +{ + sink_state = i_state; + + const std::map MyEnumStrings { + { SINK_NOT_INIT, "SINK_NOT_INIT" }, + { SINK_READY, "SINK_READY" }, + { SINK_ERROR, "SINK_ERROR" }, + { SINK_COM_OPEN, "SINK_COM_OPEN" }, + { SINK_COM_IN_PROGRESS, "SINK_COM_IN_PROGRESS" }, + }; + + auto it = MyEnumStrings.find(sink_state); /* FIXME: we issue a warning, but the variable app_state is now out of bounds */ + std::string error_str = it == MyEnumStrings.end() ? "OUT_OF_RANGE" : it->second; + clogI << "SINK State change : " << error_str << std::endl; } \ No newline at end of file diff --git a/src/domain/zigbee-tools/green-power-sink.h b/src/domain/zigbee-tools/green-power-sink.h index 159e22f1..0e540b4b 100644 --- a/src/domain/zigbee-tools/green-power-sink.h +++ b/src/domain/zigbee-tools/green-power-sink.h @@ -15,6 +15,14 @@ #include #endif // USE_RARITAN +typedef enum +{ + SINK_NOT_INIT, // starting state + SINK_READY, // default state if no action in progress + SINK_ERROR, // something wrong + SINK_COM_OPEN, // GP Proxy Commissioning mode open + SINK_COM_IN_PROGRESS, // GP sink receive gpf comm frame +}ESinkState; class CGpSink : public CEzspDongleObserver { @@ -60,6 +68,8 @@ class CGpSink : public CEzspDongleObserver CEzspDongle &dongle; CZigbeeMessaging &zb_messaging; CGpSinkTable sink_table; + ESinkState sink_state; + CGpFrame gpf_comm_frame; /** * Notify Observer of this class @@ -67,6 +77,7 @@ class CGpSink : public CEzspDongleObserver std::set observers; void notifyObserversOfRxGpFrame( CGpFrame i_gpf ); + void setSinkState( ESinkState i_state ); /** * @brief send zigbee unicast message GP Proxy Commissioning Mode. @@ -74,6 +85,28 @@ class CGpSink : public CEzspDongleObserver * WARNING all parameters are hardcoded for testing */ void sendLocalGPProxyCommissioningMode(void); + + /** + * Retrieves the sink table entry stored at the passed index. + */ + void gpSinkGetEntry( uint8_t i_index ); + + /** + * @brief Finds or allocates a sink entry + * + * @param i_src_id : gpd address to be found + */ + void gpSinkTableFindOrAllocateEntry( uint32_t i_src_id ); + + /** + * Retrieves the sink table entry stored at the passed index. + */ + void gpSinkSetEntry( uint8_t i_index, std::vector i_struct ); + + /** + * Update the GP Proxy table based on a GP pairing. + */ + void gpProxyTableProcessGpPairing( std::vector i_param ); }; #ifdef USE_RARITAN From dd66dcbc62e7748e6a69e81cd468c3e61d258b7a Mon Sep 17 00:00:00 2001 From: seb Date: Wed, 13 Nov 2019 15:47:47 +0100 Subject: [PATCH 05/44] adding class to manage ember gp sink table entry structure --- src/Makefile | 6 +- .../ember-gp-sink-table-entry-struct.cpp | 97 ++++++++++++++++++- .../struct/ember-gp-sink-table-entry-struct.h | 56 ++++++++++- src/libezsp.mk.inc | 1 + 4 files changed, 156 insertions(+), 4 deletions(-) diff --git a/src/Makefile b/src/Makefile index 3444c5aa..26ea08cc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -27,6 +27,7 @@ libezsp_SRCS = domain/zbmessage/zigbee-message.cpp \ domain/ezsp-protocol/struct/ember-network-parameters.cpp \ domain/ezsp-protocol/struct/ember-child-data-struct.cpp \ domain/ezsp-protocol/struct/ember-gp-address-struct.cpp \ + domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp \ domain/ezsp-dongle.cpp \ domain/ash.cpp \ spi/GenericAsyncDataInputObservable.cpp \ @@ -43,7 +44,6 @@ libezspincludedir = $(includedir)/include/local/ezsp libezspinclude_HEADERS = domain/zbmessage/zdp-enum.h \ domain/ezsp-protocol/ezsp-enum.h \ -domain/ezsp-protocol/struct/ember-key-struct.h \ domain/ezsp-protocol/get-network-parameters-response.h \ domain/byte-manip.h \ domain/ash.h \ @@ -61,7 +61,11 @@ domain/zbmessage/aps.h \ domain/zbmessage/apsoption.h \ domain/zbmessage/zclheader.h \ domain/zbmessage/zclframecontrol.h \ +domain/ezsp-protocol/struct/ember-key-struct.h \ domain/ezsp-protocol/struct/ember-network-parameters.h \ +domain/ezsp-protocol/struct/ember-child-data-struct.h \ +domain/ezsp-protocol/struct/ember-gp-address-struct.h \ +domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h \ spi/raritan/RaritanTimerFactory.h \ spi/raritan/RaritanEventLoop.h \ spi/raritan/RaritanUartDriver.h \ diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp index 3cd7ad9a..9cec0931 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp @@ -11,7 +11,102 @@ #include "../../byte-manip.h" -CEmberGpSinkTableEntryStruct::CEmberGpSinkTableEntryStruct(const std::vector& raw_message) +CEmberGpSinkTableEntryStruct::CEmberGpSinkTableEntryStruct(const std::vector& raw_message): + status(raw_message.at(0)), + options(dble_u8_to_u16(raw_message.at(1),raw_message.at(2))), + gpd(std::vector(raw_message.begin()+3,raw_message.end())), + device_id(raw_message.at(13)), + sink_list(), + assigned_alias(dble_u8_to_u16(raw_message.at(36),raw_message.at(37))), + groupcast_radius(raw_message.at(38)), + security_options(raw_message.at(39)), + gpdSecurity_frame_counter(static_cast(quad_u8_to_u32(raw_message.at(40),raw_message.at(41),raw_message.at(42),raw_message.at(43)))), + gpd_key(raw_message.begin()+44,raw_message.begin()+60) { + sink_list[0].push_back(0xFF); + sink_list[1].push_back(0xFF); +} +/** + * @brief constructor with specific value, others are set to default value. + * option : 0x02A8 (cf. A3.3.2.2.1 Options parameter of the Sink Table from doc doc-14-0563-16-batt-green-power-spec_ProxyBasic.pdf) + * - bits 0..2 : Application Id (0b000 : use source Id) + * - bits 3..4 : Communication mode (0b01 : groupcast forwarding of the GP Notification command to DGroupID) + * - bit 5 : Sequence number capabilities (0b1 : use incremental sequence number) + * - bit 6 : RxOnCapability (0b0 : not capable) + * - bit 7 : FixedLocation (0b1 : not a mobile device) + * - bit 8 : AssignedAlias (0b0 : the derived alias is used) + * - bit 9 : Security use (0b1 : indicates that security-related parameters of the Sink Table entry are present) + * - bit 10..15 : Reserved + * sink_list : by reverse set first byte of each to 0xFF to disable usage. + * groupcast_radius : The default value of 0x00 indicates undefined + * + * @param i_status Internal status of the sink table entry. 0x01 active, 0xff : disable + * @param i_gpd_address The addressing info of the GPD. + * @param i_device_id The device id for the GPD. + * @param i_alias The assigned alias for the GPD. + * @param i_security_option The security options field. currently 0x12 : SecurtityLevel (0b10), SecurityKeyType(0b100) + * @param i_frm_counter the last observed valid frame counter value + * @param i_gpd_key The key to use for GPD. + */ +CEmberGpSinkTableEntryStruct::CEmberGpSinkTableEntryStruct(EmberGpSinkTableEntryStatus i_status, + CEmberGpAddressStruct i_gpd_address, uint8_t i_device_id, uint16_t i_alias, + uint8_t i_security_option, EmberGpSecurityFrameCounter i_frm_counter, EmberKeyData i_gpd_key): + status(i_status), + options(0x02A8), + gpd(i_gpd_address), + device_id(i_device_id), + sink_list(), + assigned_alias(i_alias), + groupcast_radius(0), + security_options(i_security_option), + gpdSecurity_frame_counter(i_frm_counter), + gpd_key(i_gpd_key) +{ + sink_list[0].push_back(0xFF); + sink_list[1].push_back(0xFF); +} + + +/** + * @brief return structure as a raw + * + * @return raw of structure + */ +std::vector CEmberGpSinkTableEntryStruct::getRaw(void) +{ + std::vector l_struct; + + // Internal status of the sink table entry. + l_struct.push_back(status); // 0x01 : active, 0xff : disable + // The tunneling options (this contains both options and extendedOptions from the spec). WARNING 16 bits !!! + l_struct.push_back(u16_get_lo_u8(options)); + l_struct.push_back(u16_get_hi_u8(options)); + // The addressing info of the GPD. + std::vector l_addr = gpd.getRaw(); + l_struct.insert(l_struct.end(), l_addr.begin(), l_addr.end()); + // The device id for the GPD. + l_struct.push_back(device_id); + // The list of sinks (hardcoded to 2 which is the spec minimum). + for( int loop=0; loop(gpdSecurity_frame_counter&0xFF)); + l_struct.push_back(static_cast((gpdSecurity_frame_counter>>8)&0xFF)); + l_struct.push_back(static_cast((gpdSecurity_frame_counter>>16)&0xFF)); + l_struct.push_back(static_cast((gpdSecurity_frame_counter>>24)&0xFF)); + + // The key to use for GPD. + l_struct.insert(l_struct.end(), gpd_key.begin(), gpd_key.end()); + + return l_struct; } \ No newline at end of file diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h index 66f98c8f..f3c9920f 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h @@ -7,6 +7,7 @@ #pragma once #include "../ezsp-enum.h" +#include "ember-gp-address-struct.h" #ifdef USE_RARITAN /**** Start of the official API; no includes below this point! ***************/ @@ -30,6 +31,32 @@ class CEmberGpSinkTableEntryStruct */ CEmberGpSinkTableEntryStruct(const std::vector& raw_message); + /** + * @brief constructor with specific value, others are set to default value. + * option : 0x02A8 (cf. A3.3.2.2.1 Options parameter of the Sink Table from doc doc-14-0563-16-batt-green-power-spec_ProxyBasic.pdf) + * - bits 0..2 : Application Id (0b000 : use source Id) + * - bits 3..4 : Communication mode (0b01 : groupcast forwarding of the GP Notification command to DGroupID) + * - bit 5 : Sequence number capabilities (0b1 : use incremental sequence number) + * - bit 6 : RxOnCapability (0b0 : not capable) + * - bit 7 : FixedLocation (0b1 : not a mobile device) + * - bit 8 : AssignedAlias (0b0 : the derived alias is used) + * - bit 9 : Security use (0b1 : indicates that security-related parameters of the Sink Table entry are present) + * - bit 10..15 : Reserved + * sink_list : by reverse set first byte of each to 0xFF to disable usage. + * groupcast_radius : The default value of 0x00 indicates undefined + * + * @param i_status Internal status of the sink table entry. 0x01 active, 0xff : disable + * @param i_gpd_address The addressing info of the GPD. + * @param i_device_id The device id for the GPD. + * @param i_alias The assigned alias for the GPD. + * @param i_security_option The security options field. currently 0x12 : SecurtityLevel (0b10), SecurityKeyType(0b100) + * @param i_frm_counter the last observed valid frame counter value + * @param i_gpd_key The key to use for GPD. + */ + CEmberGpSinkTableEntryStruct(EmberGpSinkTableEntryStatus i_status, + CEmberGpAddressStruct i_gpd_address, uint8_t i_device_id, uint16_t i_alias, + uint8_t i_security_option, EmberGpSecurityFrameCounter i_frm_counter, EmberKeyData i_gpd_key); + /** * @brief Copy constructor * @@ -44,10 +71,35 @@ class CEmberGpSinkTableEntryStruct */ CEmberGpSinkTableEntryStruct& operator=(const CEmberGpSinkTableEntryStruct& other) = delete; - private: - + /** + * @brief return structure as a raw + * + * @return raw of structure + */ + std::vector getRaw(void); + private: + // Internal status of the sink table entry. + EmberGpSinkTableEntryStatus status; + // The tunneling options (this contains both options and extendedOptions from the spec). WRONG Specification only 16 bits like option without extended ... + uint16_t options; + // The addressing info of the GPD. + CEmberGpAddressStruct gpd; + // The device id for the GPD. + uint8_t device_id; + // The list of sinks (hardcoded to 2 which is the spec minimum). + EmberGpSinkListEntry sink_list[GP_SINK_LIST_ENTRIES]; + // The assigned alias for the GPD. + EmberNodeId assigned_alias; + // The groupcast radius. + uint8_t groupcast_radius; + // The security options field. + uint8_t security_options; + // The security frame counter of the GPD. + EmberGpSecurityFrameCounter gpdSecurity_frame_counter; + // The key to use for GPD. + EmberKeyData gpd_key; }; #ifdef USE_RARITAN diff --git a/src/libezsp.mk.inc b/src/libezsp.mk.inc index f3d28d04..526948c8 100644 --- a/src/libezsp.mk.inc +++ b/src/libezsp.mk.inc @@ -15,6 +15,7 @@ LIBEZSP_COMMON_SRC = \ $(SRC_DOMAIN_PATH)/ezsp-protocol/struct/ember-key-struct.cpp \ $(SRC_DOMAIN_PATH)/ezsp-protocol/struct/ember-child-data-struct.cpp \ $(SRC_DOMAIN_PATH)/ezsp-protocol/struct/ember-gp-address-struct.cpp \ + $(SRC_DOMAIN_PATH)/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp \ $(SRC_DOMAIN_PATH)/zigbee-tools/zigbee-networking.cpp \ $(SRC_DOMAIN_PATH)/zigbee-tools/zigbee-messaging.cpp \ $(SRC_DOMAIN_PATH)/zigbee-tools/green-power-sink.cpp \ From a6d4359c6a51b3230aaa6cb3828fb5bfdebbd50f Mon Sep 17 00:00:00 2001 From: seb Date: Wed, 13 Nov 2019 15:48:18 +0100 Subject: [PATCH 06/44] adding typedef associate to gp type --- src/domain/ezsp-protocol/ezsp-enum.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/domain/ezsp-protocol/ezsp-enum.h b/src/domain/ezsp-protocol/ezsp-enum.h index 8b2477e6..e928dff1 100644 --- a/src/domain/ezsp-protocol/ezsp-enum.h +++ b/src/domain/ezsp-protocol/ezsp-enum.h @@ -1045,6 +1045,26 @@ class CEzspEnum{ static std::string EmberIncomingMessageTypeToString( EmberIncomingMessageType in ); }; +// The security level of the GPD. +typedef uint8_t EmberGpSecurityLevel; + +// The type of security key to use for the GPD. +typedef uint8_t EmberGpKeyType; + +// The proxy table entry status +typedef uint8_t EmberGpProxyTableEntryStatus; + +// The security frame counter +typedef uint32_t EmberGpSecurityFrameCounter; + +// The sink table entry status +typedef uint8_t EmberGpSinkTableEntryStatus; + +#define GP_SINK_LIST_ENTRIES 2 // hardcoded to 2 which is the spec minimum (cf. A.3.4.2.2.6 Sink group list parameter from doc-14-0563-16-batt-green-power-spec_ProxyBasic.pdf) +#define EMBER_GP_SINK_LIST_ENTRY_SIZE 11 // why ? first byte to 0xFF is for not used ! +typedef std::vector EmberGpSinkListEntry; + + #ifdef USE_RARITAN #include #endif // USE_RARITAN From a720226e7d0fbb6c0b5b17abeb397cc4ec259dc9 Mon Sep 17 00:00:00 2001 From: seb Date: Wed, 13 Nov 2019 15:49:15 +0100 Subject: [PATCH 07/44] rework member of class. adding new constructor --- .../struct/ember-gp-address-struct.cpp | 57 ++++++++++++++----- .../struct/ember-gp-address-struct.h | 27 ++++++++- 2 files changed, 68 insertions(+), 16 deletions(-) diff --git a/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp b/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp index 0eb00792..d9cc9e43 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp +++ b/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp @@ -5,42 +5,73 @@ */ #include #include -#include "../../byte-manip.h" #include "ember-gp-address-struct.h" +/** + * @brief Construction from itself + * + * @param i_gpd_address gpd address from construct + */ +CEmberGpAddressStruct::CEmberGpAddressStruct(const CEmberGpAddressStruct& i_gpd_address): + gpdIeeeAddress(i_gpd_address.getGpdIeeeAddress()), + applicationId(i_gpd_address.getApplicationId()), + endpoint(i_gpd_address.getEndpoint()) +{ +} + CEmberGpAddressStruct::CEmberGpAddressStruct(const std::vector& raw_message): + gpdIeeeAddress(raw_message.begin()+1,raw_message.begin()+1+EMBER_EUI64_BYTE_SIZE), + applicationId(raw_message.at(0)), + endpoint(raw_message.at(EMBER_EUI64_BYTE_SIZE+1)) +{ +} + +CEmberGpAddressStruct::CEmberGpAddressStruct(const uint32_t i_srcId): gpdIeeeAddress(), /* FIXME */ - sourceId(0), applicationId(0), endpoint(0) { + // update Ieee with twice SourceId + gpdIeeeAddress.push_back(static_cast(i_srcId&0xFF)); + gpdIeeeAddress.push_back(static_cast((i_srcId>>8)&0xFF)); + gpdIeeeAddress.push_back(static_cast((i_srcId>>16)&0xFF)); + gpdIeeeAddress.push_back(static_cast((i_srcId>>24)&0xFF)); + gpdIeeeAddress.push_back(static_cast(i_srcId&0xFF)); + gpdIeeeAddress.push_back(static_cast((i_srcId>>8)&0xFF)); + gpdIeeeAddress.push_back(static_cast((i_srcId>>16)&0xFF)); + gpdIeeeAddress.push_back(static_cast((i_srcId>>24)&0xFF)); +} + +std::vector CEmberGpAddressStruct::getRaw(void) +{ + std::vector lo_raw; + + // application Id + lo_raw.push_back(applicationId); + + // Ieee | sourceId for(uint8_t loop=0; loop& raw_message); + /** + * @brief Construct from sourceId + * + * @param i_srcId SourceId to construct from + */ + CEmberGpAddressStruct(const uint32_t i_srcId); + /** * @brief Assignment operator * @@ -37,9 +52,9 @@ class CEmberGpAddressStruct EmberEUI64 getGpdIeeeAddress() const { return gpdIeeeAddress; } /** - * @brief The GPD's source ID. + * @brief The GPD's source ID. not mention in ezsp specification but ieee and sourceId is an union */ - uint32_t getSourceId() const { return sourceId; } + uint32_t getSourceId() const { return quad_u8_to_u32(gpdIeeeAddress.at(3), gpdIeeeAddress.at(2), gpdIeeeAddress.at(1), gpdIeeeAddress.at(0)); } /** * @brief The GPD Application ID. @@ -51,6 +66,13 @@ class CEmberGpAddressStruct */ uint8_t getEndpoint() const { return endpoint; } + /** + * @brief return a raw buffer + * + * @return raw buffer + */ + std::vector getRaw(void); + /** * @brief Dump this instance as a string * @@ -71,7 +93,6 @@ class CEmberGpAddressStruct private: EmberEUI64 gpdIeeeAddress; // The GPD's EUI64. - uint32_t sourceId; // The GPD's source ID. uint8_t applicationId; // The GPD Application ID. uint8_t endpoint; // The GPD endpoint. From f9a9590a015d958bb983775d8bc5d83fff323eef Mon Sep 17 00:00:00 2001 From: seb Date: Wed, 13 Nov 2019 15:50:57 +0100 Subject: [PATCH 08/44] using structure class in place of raw vector. adding parameter to commissioning function to be able to open/close --- src/domain/zigbee-tools/green-power-sink.cpp | 200 +++++-------------- src/domain/zigbee-tools/green-power-sink.h | 25 ++- 2 files changed, 72 insertions(+), 153 deletions(-) diff --git a/src/domain/zigbee-tools/green-power-sink.cpp b/src/domain/zigbee-tools/green-power-sink.cpp index 5a94f21b..75eda0b6 100644 --- a/src/domain/zigbee-tools/green-power-sink.cpp +++ b/src/domain/zigbee-tools/green-power-sink.cpp @@ -11,6 +11,8 @@ #include "green-power-sink.h" #include "../ezsp-protocol/struct/ember-gp-address-struct.h" +#include "../byte-manip.h" + #include "../../domain/zbmessage/zigbee-message.h" #include "../../spi/GenericLogger.h" @@ -77,15 +79,33 @@ void CGpSink::init(void) setSinkState(SINK_READY); } +/** + * Clear all GP tables + */ +void CGpSink::gpClearAllTables( void ) +{ + // sink table + dongle.sendCommand(EZSP_GP_SINK_TABLE_CLEAR_ALL); +} + void CGpSink::openCommissioningSession(void) { // set local proxy in commissioning mode - sendLocalGPProxyCommissioningMode(); + sendLocalGPProxyCommissioningMode(0x05); // set state setSinkState(SINK_COM_OPEN); } +void CGpSink::closeCommissioningSession(void) +{ + // set local proxy in commissioning mode + sendLocalGPProxyCommissioningMode(0x00); + + // set state + setSinkState(SINK_READY); +} + uint8_t CGpSink::registerGpd( uint32_t i_source_id ) { CGpSinkTableEntry l_entry = CGpSinkTableEntry(i_source_id); @@ -93,6 +113,11 @@ uint8_t CGpSink::registerGpd( uint32_t i_source_id ) return sink_table.addEntry(l_entry); } +void CGpSink::registerGpd( uint32_t i_source_id, std::vector i_key ) +{ + +} + void CGpSink::handleDongleState( EDongleState i_state ) { } @@ -186,85 +211,18 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re { if( SINK_COM_IN_PROGRESS == sink_state ) { - // set the entry with new parameters - std::vector l_struct; - uint32_t l_src_id = gpf_comm_frame.getSourceId(); - // Internal status of the sink table entry. - l_struct.push_back(0x01); // active, 0xff : disable - // The tunneling options (this contains both options and extendedOptions from the spec). WARNING 16 bits !!! - l_struct.push_back(0xA8); - l_struct.push_back(0x02); - // The addressing info of the GPD. - l_struct.push_back(0x00); // short address - l_struct.push_back(static_cast(l_src_id&0xFF)); - l_struct.push_back(static_cast((l_src_id>>8)&0xFF)); - l_struct.push_back(static_cast((l_src_id>>16)&0xFF)); - l_struct.push_back(static_cast((l_src_id>>24)&0xFF)); - l_struct.push_back(static_cast(l_src_id&0xFF)); - l_struct.push_back(static_cast((l_src_id>>8)&0xFF)); - l_struct.push_back(static_cast((l_src_id>>16)&0xFF)); - l_struct.push_back(static_cast((l_src_id>>24)&0xFF)); - l_struct.push_back(0x00); // endpoint -> not used - // The device id for the GPD. - l_struct.push_back(gpf_comm_frame.getPayload().at(0)); // 0x02 - // The list of sinks (hardcoded to 2 which is the spec minimum). - l_struct.push_back(0xFF); // unused - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0xFF); // unused - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - // The assigned alias for the GPD. - l_struct.push_back(static_cast(l_src_id&0xFF)); - l_struct.push_back(static_cast((l_src_id>>8)&0xFF)); + // construct sink table entry + EmberKeyData l_harcoded_key{0x59, 0x13, 0x29, 0x50, 0x28, 0x9D, 0x14, 0xFD, + 0x73, 0xF9, 0xC3, 0x25, 0xD4, 0x57, 0xAB, 0xB5}; + CEmberGpAddressStruct l_gpd_addr(gpf_comm_frame.getSourceId()); - // The groupcast radius. - l_struct.push_back(0x00); - - // The security options field. - l_struct.push_back(0x12); - - // The security frame counter of the GPD. - l_struct.push_back(gpf_comm_frame.getPayload().at(23)); - l_struct.push_back(gpf_comm_frame.getPayload().at(24)); - l_struct.push_back(gpf_comm_frame.getPayload().at(25)); - l_struct.push_back(gpf_comm_frame.getPayload().at(26)); + CEmberGpSinkTableEntryStruct l_entry(0x01, l_gpd_addr, gpf_comm_frame.getPayload().at(0), + static_cast(gpf_comm_frame.getSourceId()&0xFFFF), 0x12, + quad_u8_to_u32(gpf_comm_frame.getPayload().at(23),gpf_comm_frame.getPayload().at(24),gpf_comm_frame.getPayload().at(25),gpf_comm_frame.getPayload().at(26)), + l_harcoded_key ); - // The key to use for GPD. 59 13 29 50 28 9D 14 FD 73 F9 C3 25 D4 57 AB B5 - l_struct.push_back(0x59); - l_struct.push_back(0x13); - l_struct.push_back(0x29); - l_struct.push_back(0x50); - l_struct.push_back(0x28); - l_struct.push_back(0x9D); - l_struct.push_back(0x14); - l_struct.push_back(0xFD); - l_struct.push_back(0x73); - l_struct.push_back(0xF9); - l_struct.push_back(0xC3); - l_struct.push_back(0x25); - l_struct.push_back(0xD4); - l_struct.push_back(0x57); - l_struct.push_back(0xAB); - l_struct.push_back(0xB5); // call - gpSinkSetEntry(0,l_struct); + gpSinkSetEntry(0,l_entry); } } @@ -349,8 +307,8 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re { clogI << "CGpSink::ezspHandler EZSP_GP_PROXY_TABLE_PROCESS_GP_PAIRING gpPairingAdded : " << std::hex << std::setw(2) << std::setfill('0') << static_cast(i_msg_receive[0]) << std::endl; - // set new state - setSinkState(SINK_READY); + // close commissioning session + closeCommissioningSession(); } } break; @@ -386,7 +344,7 @@ void CGpSink::notifyObserversOfRxGpFrame( CGpFrame i_gpf ) { } } -void CGpSink::sendLocalGPProxyCommissioningMode(void) +void CGpSink::sendLocalGPProxyCommissioningMode(uint8_t i_option) { // forge GP Proxy Commissioning Mode command // assume we are coordinator of network and our nodeId is 0 @@ -400,7 +358,7 @@ void CGpSink::sendLocalGPProxyCommissioningMode(void) // bit4 (channel present) : 0b0 / shall always be set to 0 according current spec. // bit5 (unicast communication) : 0b0 / send GP Commissioning Notification commands in broadcast // bit6-7 (reserved) - l_gp_comm_payload.push_back(0x05); + l_gp_comm_payload.push_back(i_option); // 0x05 => open // comm windows 2 bytes // present only if exit mode flag On commissioning Window expiration (bit0) is set @@ -418,53 +376,10 @@ void CGpSink::sendLocalGPProxyCommissioningMode(void) l_gp_comm_msg.aps.src_ep = GP_ENDPOINT; // - clogI << "SEND UNICAST : OPEN GP COMMISSIONING\n"; + clogI << "SEND UNICAST : OPEN/CLOSE GP COMMISSIONING option : " << std::hex << std::setw(2) << std::setfill('0') << i_option << std::endl; zb_messaging.SendUnicast(0,l_gp_comm_msg); } -/* -void CGpSink::gpCloseCommissioning() -{ - std::vector l_payload; - - // The action to perform on the GP TX queue (true to add, false to remove). - l_payload.push_back(0x00); - - // Whether to use ClearChannelAssessment when transmitting the GPDF. - l_payload.push_back(0x00); - - // The Address of the destination GPD. - l_payload.push_back(0x00); - l_payload.push_back(0xFF); - l_payload.push_back(0xFF); - l_payload.push_back(0xFF); - l_payload.push_back(0xFF); - l_payload.push_back(0xFF); - l_payload.push_back(0xFF); - l_payload.push_back(0xFF); - l_payload.push_back(0xFF); - l_payload.push_back(0x7F); - - // The GPD command ID to send. - l_payload.push_back(0x00); - - // The length of the GP command payload. - l_payload.push_back(0x01); - - // The GP command payload. - l_payload.push_back(0x00); - - // The handle to refer to the GPDF. - l_payload.push_back(0x00); - - // How long to keep the GPDF in the TX Queue. - l_payload.push_back(0x00); - - clogI << "EZSP_D_GP_SEND : CLOSE GP COMMISSIONING\n"; - dongle.sendCommand(EZSP_D_GP_SEND,l_payload); -} -*/ - /* void CGpSink::gpBrCommissioningNotification( uint32_t i_gpd_src_id, uint8_t i_seq_number ) { @@ -598,21 +513,11 @@ void CAppDemo::gpSinkTableLookup( uint32_t i_src_id ) */ void CGpSink::gpSinkTableFindOrAllocateEntry( uint32_t i_src_id ) { - std::vector l_payload; - // An EmberGpAddress struct containing a copy of the gpd address to be found. - l_payload.push_back(0x00); - l_payload.push_back((uint8_t)(i_src_id&0xFF)); - l_payload.push_back((uint8_t)((i_src_id>>8)&0xFF)); - l_payload.push_back((uint8_t)((i_src_id>>16)&0xFF)); - l_payload.push_back((uint8_t)((i_src_id>>24)&0xFF)); - l_payload.push_back((uint8_t)(i_src_id&0xFF)); - l_payload.push_back((uint8_t)((i_src_id>>8)&0xFF)); - l_payload.push_back((uint8_t)((i_src_id>>16)&0xFF)); - l_payload.push_back((uint8_t)((i_src_id>>24)&0xFF)); - l_payload.push_back(0x00); + CEmberGpAddressStruct l_gp_address(i_src_id); - dongle.sendCommand(EZSP_GP_SINK_TABLE_FIND_OR_ALLOCATE_ENTRY,l_payload); + clogI << "EZSP_GP_SINK_TABLE_FIND_OR_ALLOCATE_ENTRY\n"; + dongle.sendCommand(EZSP_GP_SINK_TABLE_FIND_OR_ALLOCATE_ENTRY,l_gp_address.getRaw()); } /** @@ -631,9 +536,12 @@ void CGpSink::gpSinkGetEntry( uint8_t i_index ) /** - * Retrieves the sink table entry stored at the passed index. + * @brief Retrieves the sink table entry stored at the passed index. + * + * @param i_index The index of the requested sink table entry. + * @param i_entry An EmberGpSinkTableEntry struct containing a copy of the sink entry to be updated. */ -void CGpSink::gpSinkSetEntry( uint8_t i_index, std::vector i_struct ) +void CGpSink::gpSinkSetEntry( uint8_t i_index, CEmberGpSinkTableEntryStruct& i_entry ) { std::vector l_payload; @@ -641,6 +549,7 @@ void CGpSink::gpSinkSetEntry( uint8_t i_index, std::vector i_struct ) l_payload.push_back(i_index); // struct + std::vector i_struct = i_entry.getRaw(); l_payload.insert(l_payload.end(), i_struct.begin(), i_struct.end()); clogI << "EZSP_GP_SINK_TABLE_SET_ENTRY\n"; @@ -663,16 +572,7 @@ void CGpSink::gpProxyTableProcessGpPairing( std::vector i_param ) } -/** - * Clear all GP tables - */ -/* -void CAppDemo::gpClearAllTables( void ) -{ - // sink table - dongle.sendCommand(EZSP_GP_SINK_TABLE_CLEAR_ALL); -} -*/ + diff --git a/src/domain/zigbee-tools/green-power-sink.h b/src/domain/zigbee-tools/green-power-sink.h index 0e540b4b..1716929f 100644 --- a/src/domain/zigbee-tools/green-power-sink.h +++ b/src/domain/zigbee-tools/green-power-sink.h @@ -9,6 +9,7 @@ #include "../ezsp-dongle.h" #include "zigbee-messaging.h" #include "green-power-sink-table.h" +#include "../ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h" #ifdef USE_RARITAN /**** Start of the official API; no includes below this point! ***************/ @@ -39,11 +40,21 @@ class CGpSink : public CEzspDongleObserver */ void init(void); + /** + * Clear all GP tables + */ + void gpClearAllTables( void ); + /** * @brief Open a commissioning session for limited time, close as soon as a binding is done. */ void openCommissioningSession(void); + /** + * @brief Force to close commissioning session + */ + void closeCommissioningSession(void); + /** * @brief add a green power sink table entry * @@ -51,6 +62,11 @@ class CGpSink : public CEzspDongleObserver */ uint8_t registerGpd( uint32_t i_source_id ); + /** + * @brief add a green power device + */ + void registerGpd( uint32_t i_source_id, std::vector i_key ); + /** * Observer */ @@ -84,7 +100,7 @@ class CGpSink : public CEzspDongleObserver * done from sink to local dongle. * WARNING all parameters are hardcoded for testing */ - void sendLocalGPProxyCommissioningMode(void); + void sendLocalGPProxyCommissioningMode(uint8_t i_option); /** * Retrieves the sink table entry stored at the passed index. @@ -99,9 +115,12 @@ class CGpSink : public CEzspDongleObserver void gpSinkTableFindOrAllocateEntry( uint32_t i_src_id ); /** - * Retrieves the sink table entry stored at the passed index. + * @brief Retrieves the sink table entry stored at the passed index. + * + * @param i_index The index of the requested sink table entry. + * @param i_entry An EmberGpSinkTableEntry struct containing a copy of the sink entry to be updated. */ - void gpSinkSetEntry( uint8_t i_index, std::vector i_struct ); + void gpSinkSetEntry( uint8_t i_index, CEmberGpSinkTableEntryStruct& i_entry ); /** * Update the GP Proxy table based on a GP pairing. From 41165d55cad203bcb1e1c7e325c65b915effe641 Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 14 Nov 2019 18:36:57 +0100 Subject: [PATCH 09/44] minimal aes class --- src/domain/custom-aes.cpp | 298 ++++++++++++++++++++++++++++++++++++++ src/domain/custom-aes.h | 248 +++++++++++++++++++++++++++++++ 2 files changed, 546 insertions(+) create mode 100644 src/domain/custom-aes.cpp create mode 100644 src/domain/custom-aes.h diff --git a/src/domain/custom-aes.cpp b/src/domain/custom-aes.cpp new file mode 100644 index 00000000..42d6da6b --- /dev/null +++ b/src/domain/custom-aes.cpp @@ -0,0 +1,298 @@ +/* + --------------------------------------------------------------------------- + Copyright (c) 2013, Igor Saric. All rights reserved. + + LICENSE TERMS + + The redistribution and use of this software (with or without changes) + is allowed without the payment of fees or royalties provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + --------------------------------------------------------------------------- + Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The redistribution and use of this software (with or without changes) + is allowed without the payment of fees or royalties provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + */ + +#include "custom-aes.h" + +#include + +CAes::CAes() : + context() +{ +} + + +// algorithm +void CAes::xor_block( void *d, const void *s ) +{ + ((uint32_t*)d)[ 0] ^= ((uint32_t*)s)[ 0]; + ((uint32_t*)d)[ 1] ^= ((uint32_t*)s)[ 1]; + ((uint32_t*)d)[ 2] ^= ((uint32_t*)s)[ 2]; + ((uint32_t*)d)[ 3] ^= ((uint32_t*)s)[ 3]; +} + +void CAes::copy_and_key( void *d, const void *s, const void *k ) +{ + ((uint32_t*)d)[ 0] = ((uint32_t*)s)[ 0] ^ ((uint32_t*)k)[ 0]; + ((uint32_t*)d)[ 1] = ((uint32_t*)s)[ 1] ^ ((uint32_t*)k)[ 1]; + ((uint32_t*)d)[ 2] = ((uint32_t*)s)[ 2] ^ ((uint32_t*)k)[ 2]; + ((uint32_t*)d)[ 3] = ((uint32_t*)s)[ 3] ^ ((uint32_t*)k)[ 3]; +} + +void CAes::add_round_key( uint8_t d[N_BLOCK], const uint8_t k[N_BLOCK] ) +{ + xor_block(d, k); +} + +void CAes::shift_sub_rows( uint8_t st[N_BLOCK] ) +{ + uint8_t tt; + + st[ 0] = s_box(st[ 0]); st[ 4] = s_box(st[ 4]); + st[ 8] = s_box(st[ 8]); st[12] = s_box(st[12]); + + tt = st[1]; st[ 1] = s_box(st[ 5]); st[ 5] = s_box(st[ 9]); + st[ 9] = s_box(st[13]); st[13] = s_box( tt ); + + tt = st[2]; st[ 2] = s_box(st[10]); st[10] = s_box( tt ); + tt = st[6]; st[ 6] = s_box(st[14]); st[14] = s_box( tt ); + + tt = st[15]; st[15] = s_box(st[11]); st[11] = s_box(st[ 7]); + st[ 7] = s_box(st[ 3]); st[ 3] = s_box( tt ); +} + +void CAes::inv_shift_sub_rows( uint8_t st[N_BLOCK] ) +{ + uint8_t tt; + + st[ 0] = is_box(st[ 0]); st[ 4] = is_box(st[ 4]); + st[ 8] = is_box(st[ 8]); st[12] = is_box(st[12]); + + tt = st[13]; st[13] = is_box(st[9]); st[ 9] = is_box(st[5]); + st[ 5] = is_box(st[1]); st[ 1] = is_box( tt ); + + tt = st[2]; st[ 2] = is_box(st[10]); st[10] = is_box( tt ); + tt = st[6]; st[ 6] = is_box(st[14]); st[14] = is_box( tt ); + + tt = st[3]; st[ 3] = is_box(st[ 7]); st[ 7] = is_box(st[11]); + st[11] = is_box(st[15]); st[15] = is_box( tt ); +} + +void CAes::mix_sub_columns( uint8_t dt[N_BLOCK] ) +{ + uint8_t st[N_BLOCK]; + block_copy(st, dt); + + dt[ 0] = gfm2_sb(st[0]) ^ gfm3_sb(st[5]) ^ s_box(st[10]) ^ s_box(st[15]); + dt[ 1] = s_box(st[0]) ^ gfm2_sb(st[5]) ^ gfm3_sb(st[10]) ^ s_box(st[15]); + dt[ 2] = s_box(st[0]) ^ s_box(st[5]) ^ gfm2_sb(st[10]) ^ gfm3_sb(st[15]); + dt[ 3] = gfm3_sb(st[0]) ^ s_box(st[5]) ^ s_box(st[10]) ^ gfm2_sb(st[15]); + + dt[ 4] = gfm2_sb(st[4]) ^ gfm3_sb(st[9]) ^ s_box(st[14]) ^ s_box(st[3]); + dt[ 5] = s_box(st[4]) ^ gfm2_sb(st[9]) ^ gfm3_sb(st[14]) ^ s_box(st[3]); + dt[ 6] = s_box(st[4]) ^ s_box(st[9]) ^ gfm2_sb(st[14]) ^ gfm3_sb(st[3]); + dt[ 7] = gfm3_sb(st[4]) ^ s_box(st[9]) ^ s_box(st[14]) ^ gfm2_sb(st[3]); + + dt[ 8] = gfm2_sb(st[8]) ^ gfm3_sb(st[13]) ^ s_box(st[2]) ^ s_box(st[7]); + dt[ 9] = s_box(st[8]) ^ gfm2_sb(st[13]) ^ gfm3_sb(st[2]) ^ s_box(st[7]); + dt[10] = s_box(st[8]) ^ s_box(st[13]) ^ gfm2_sb(st[2]) ^ gfm3_sb(st[7]); + dt[11] = gfm3_sb(st[8]) ^ s_box(st[13]) ^ s_box(st[2]) ^ gfm2_sb(st[7]); + + dt[12] = gfm2_sb(st[12]) ^ gfm3_sb(st[1]) ^ s_box(st[6]) ^ s_box(st[11]); + dt[13] = s_box(st[12]) ^ gfm2_sb(st[1]) ^ gfm3_sb(st[6]) ^ s_box(st[11]); + dt[14] = s_box(st[12]) ^ s_box(st[1]) ^ gfm2_sb(st[6]) ^ gfm3_sb(st[11]); + dt[15] = gfm3_sb(st[12]) ^ s_box(st[1]) ^ s_box(st[6]) ^ gfm2_sb(st[11]); + } + +void CAes::inv_mix_sub_columns( uint8_t dt[N_BLOCK] ) +{ + uint8_t st[N_BLOCK]; + block_copy(st, dt); + + dt[ 0] = is_box(gfm_e(st[ 0]) ^ gfm_b(st[ 1]) ^ gfm_d(st[ 2]) ^ gfm_9(st[ 3])); + dt[ 5] = is_box(gfm_9(st[ 0]) ^ gfm_e(st[ 1]) ^ gfm_b(st[ 2]) ^ gfm_d(st[ 3])); + dt[10] = is_box(gfm_d(st[ 0]) ^ gfm_9(st[ 1]) ^ gfm_e(st[ 2]) ^ gfm_b(st[ 3])); + dt[15] = is_box(gfm_b(st[ 0]) ^ gfm_d(st[ 1]) ^ gfm_9(st[ 2]) ^ gfm_e(st[ 3])); + + dt[ 4] = is_box(gfm_e(st[ 4]) ^ gfm_b(st[ 5]) ^ gfm_d(st[ 6]) ^ gfm_9(st[ 7])); + dt[ 9] = is_box(gfm_9(st[ 4]) ^ gfm_e(st[ 5]) ^ gfm_b(st[ 6]) ^ gfm_d(st[ 7])); + dt[14] = is_box(gfm_d(st[ 4]) ^ gfm_9(st[ 5]) ^ gfm_e(st[ 6]) ^ gfm_b(st[ 7])); + dt[ 3] = is_box(gfm_b(st[ 4]) ^ gfm_d(st[ 5]) ^ gfm_9(st[ 6]) ^ gfm_e(st[ 7])); + + dt[ 8] = is_box(gfm_e(st[ 8]) ^ gfm_b(st[ 9]) ^ gfm_d(st[10]) ^ gfm_9(st[11])); + dt[13] = is_box(gfm_9(st[ 8]) ^ gfm_e(st[ 9]) ^ gfm_b(st[10]) ^ gfm_d(st[11])); + dt[ 2] = is_box(gfm_d(st[ 8]) ^ gfm_9(st[ 9]) ^ gfm_e(st[10]) ^ gfm_b(st[11])); + dt[ 7] = is_box(gfm_b(st[ 8]) ^ gfm_d(st[ 9]) ^ gfm_9(st[10]) ^ gfm_e(st[11])); + + dt[12] = is_box(gfm_e(st[12]) ^ gfm_b(st[13]) ^ gfm_d(st[14]) ^ gfm_9(st[15])); + dt[ 1] = is_box(gfm_9(st[12]) ^ gfm_e(st[13]) ^ gfm_b(st[14]) ^ gfm_d(st[15])); + dt[ 6] = is_box(gfm_d(st[12]) ^ gfm_9(st[13]) ^ gfm_e(st[14]) ^ gfm_b(st[15])); + dt[11] = is_box(gfm_b(st[12]) ^ gfm_d(st[13]) ^ gfm_9(st[14]) ^ gfm_e(st[15])); + } + +// Set the cipher key for the pre-keyed version +void CAes::aes_set_key( const uint8_t key[AES_KEY_SIZE] ) +{ + uint8_t cc, rc, hi; + aes_context *ctx = &context; + // 128 only + uint8_t keylen = AES_KEY_SIZE; + + block_copy_nn(ctx->ksch, key, keylen); + hi = (keylen + 28) << 2; + ctx->rnd = (hi >> 4) - 1; + for( cc = keylen, rc = 1; cc < hi; cc += 4 ) + { uint8_t tt, t0, t1, t2, t3; + + t0 = ctx->ksch[cc - 4]; + t1 = ctx->ksch[cc - 3]; + t2 = ctx->ksch[cc - 2]; + t3 = ctx->ksch[cc - 1]; + if( cc % keylen == 0 ) + { + tt = t0; + t0 = s_box(t1) ^ rc; + t1 = s_box(t2); + t2 = s_box(t3); + t3 = s_box(tt); + rc = f2(rc); + } + else if( keylen > 24 && cc % keylen == 16 ) + { + t0 = s_box(t0); + t1 = s_box(t1); + t2 = s_box(t2); + t3 = s_box(t3); + } + tt = cc - keylen; + ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0; + ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1; + ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2; + ctx->ksch[cc + 3] = ctx->ksch[tt + 3] ^ t3; + } +} + +// Encrypt a single block of 16 bytes +aes_result CAes::aes_encrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK] ) +{ + if( context.rnd ) + { + uint8_t s1[N_BLOCK], r; + copy_and_key( s1, in, context.ksch ); + + for( r = 1 ; r < context.rnd ; ++r ) + { + mix_sub_columns( s1 ); + add_round_key( s1, context.ksch + r * N_BLOCK); + } + shift_sub_rows( s1 ); + copy_and_key( out, s1, context.ksch + r * N_BLOCK ); + } + else + return false; + return true; +} + +// CBC encrypt a number of blocks (input and return an IV) +/* +aes_result CAes::aes_cbc_encrypt(const unsigned char *in, unsigned char *out, unsigned long size, unsigned char iv[N_BLOCK], const aes_context ctx[1] ) +{ + if (size % 16 != 0) + return EXIT_FAILURE; + + unsigned long n_block = size / 16; + + while(n_block--) + { + xor_block(iv, in); + if(aes_encrypt(iv, iv, ctx) != EXIT_SUCCESS) + return EXIT_FAILURE; + memcpy(out, iv, N_BLOCK); + in += N_BLOCK; + out += N_BLOCK; + } + return EXIT_SUCCESS; +} +*/ +// Decrypt a single block of 16 bytes +/* +aes_result CAes::aes_decrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] ) +{ + if( ctx->rnd ) + { + uint8_t s1[N_BLOCK], r; + copy_and_key( s1, in, ctx->ksch + ctx->rnd * N_BLOCK ); + inv_shift_sub_rows( s1 ); + + for( r = ctx->rnd ; --r ; ) + { + add_round_key( s1, ctx->ksch + r * N_BLOCK ); + inv_mix_sub_columns( s1 ); + } + copy_and_key( out, s1, ctx->ksch ); + } + else + return -1; + return 0; +} +*/ + +// CBC decrypt a number of blocks (input and return an IV) +/* +aes_result CAes::aes_cbc_decrypt( const unsigned char *in, unsigned char *out, unsigned long size, unsigned char iv[N_BLOCK], const aes_context ctx[1] ) +{ + if (size % 16 != 0) + return EXIT_FAILURE; + + unsigned long n_block = size / 16; + + while (n_block--) + { + uint8_t tmp[N_BLOCK]; + + memcpy(tmp, in, N_BLOCK); + if(aes_decrypt(in, out, ctx) != EXIT_SUCCESS) + return EXIT_FAILURE; + xor_block(out, iv); + memcpy(iv, tmp, N_BLOCK); + in += N_BLOCK; + out += N_BLOCK; + } + return EXIT_SUCCESS; +} +*/ diff --git a/src/domain/custom-aes.h b/src/domain/custom-aes.h new file mode 100644 index 00000000..9cf1d85d --- /dev/null +++ b/src/domain/custom-aes.h @@ -0,0 +1,248 @@ +/** + * @brief Utility functions for aes 256 + */ +/* + --------------------------------------------------------------------------- + Copyright (c) 2013, Igor Saric. All rights reserved. + + LICENSE TERMS + + The redistribution and use of this software (with or without changes) + is allowed without the payment of fees or royalties provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + --------------------------------------------------------------------------- + Copyright (c) 1998-2008, Brian Gladman, Worcester, UK. All rights reserved. + + LICENSE TERMS + + The redistribution and use of this software (with or without changes) + is allowed without the payment of fees or royalties provided that: + + 1. source code distributions include the above copyright notice, this + list of conditions and the following disclaimer; + + 2. binary distributions include the above copyright notice, this list + of conditions and the following disclaimer in their documentation; + + 3. the name of the copyright holder is not used to endorse products + built using this software without specific written permission. + + DISCLAIMER + + This software is provided 'as is' with no explicit or implied warranties + in respect of its properties, including, but not limited to, correctness + and/or fitness for purpose. + --------------------------------------------------------------------------- + */ + +#pragma once + +#include +#include + +#define AES_KEY_SIZE 16 + +#define N_ROW 4 +#define N_COL 4 +#define N_BLOCK (N_ROW * N_COL) +#define N_MAX_ROUNDS 14 + +#define WPOLY 0x011b +#define BPOLY 0x1b +#define DPOLY 0x008d + +#define f1(x) (x) +#define f2(x) ((x << 1) ^ (((x >> 7) & 1) * WPOLY)) +#define f4(x) ((x << 2) ^ (((x >> 6) & 1) * WPOLY) ^ (((x >> 6) & 2) * WPOLY)) +#define f8(x) ((x << 3) ^ (((x >> 5) & 1) * WPOLY) ^ (((x >> 5) & 2) * WPOLY) \ + ^ (((x >> 5) & 4) * WPOLY)) +#define d2(x) (((x) >> 1) ^ ((x) & 1 ? DPOLY : 0)) + +#define f3(x) (f2(x) ^ x) +#define f9(x) (f8(x) ^ x) +#define fb(x) (f8(x) ^ f2(x) ^ x) +#define fd(x) (f8(x) ^ f4(x) ^ x) +#define fe(x) (f8(x) ^ f4(x) ^ f2(x)) + +#define s_box(x) sbox[(x)] +#define is_box(x) isbox[(x)] +#define gfm2_sb(x) gfm2_sbox[(x)] +#define gfm3_sb(x) gfm3_sbox[(x)] +#define gfm_9(x) gfmul_9[(x)] +#define gfm_b(x) gfmul_b[(x)] +#define gfm_d(x) gfmul_d[(x)] +#define gfm_e(x) gfmul_e[(x)] + +#define block_copy_nn(d, s, l) memcpy(d, s, l) +#define block_copy(d, s) memcpy(d, s, N_BLOCK) + +#define sb_data(w) { /* S Box data values */ \ + w(0x63), w(0x7c), w(0x77), w(0x7b), w(0xf2), w(0x6b), w(0x6f), w(0xc5),\ + w(0x30), w(0x01), w(0x67), w(0x2b), w(0xfe), w(0xd7), w(0xab), w(0x76),\ + w(0xca), w(0x82), w(0xc9), w(0x7d), w(0xfa), w(0x59), w(0x47), w(0xf0),\ + w(0xad), w(0xd4), w(0xa2), w(0xaf), w(0x9c), w(0xa4), w(0x72), w(0xc0),\ + w(0xb7), w(0xfd), w(0x93), w(0x26), w(0x36), w(0x3f), w(0xf7), w(0xcc),\ + w(0x34), w(0xa5), w(0xe5), w(0xf1), w(0x71), w(0xd8), w(0x31), w(0x15),\ + w(0x04), w(0xc7), w(0x23), w(0xc3), w(0x18), w(0x96), w(0x05), w(0x9a),\ + w(0x07), w(0x12), w(0x80), w(0xe2), w(0xeb), w(0x27), w(0xb2), w(0x75),\ + w(0x09), w(0x83), w(0x2c), w(0x1a), w(0x1b), w(0x6e), w(0x5a), w(0xa0),\ + w(0x52), w(0x3b), w(0xd6), w(0xb3), w(0x29), w(0xe3), w(0x2f), w(0x84),\ + w(0x53), w(0xd1), w(0x00), w(0xed), w(0x20), w(0xfc), w(0xb1), w(0x5b),\ + w(0x6a), w(0xcb), w(0xbe), w(0x39), w(0x4a), w(0x4c), w(0x58), w(0xcf),\ + w(0xd0), w(0xef), w(0xaa), w(0xfb), w(0x43), w(0x4d), w(0x33), w(0x85),\ + w(0x45), w(0xf9), w(0x02), w(0x7f), w(0x50), w(0x3c), w(0x9f), w(0xa8),\ + w(0x51), w(0xa3), w(0x40), w(0x8f), w(0x92), w(0x9d), w(0x38), w(0xf5),\ + w(0xbc), w(0xb6), w(0xda), w(0x21), w(0x10), w(0xff), w(0xf3), w(0xd2),\ + w(0xcd), w(0x0c), w(0x13), w(0xec), w(0x5f), w(0x97), w(0x44), w(0x17),\ + w(0xc4), w(0xa7), w(0x7e), w(0x3d), w(0x64), w(0x5d), w(0x19), w(0x73),\ + w(0x60), w(0x81), w(0x4f), w(0xdc), w(0x22), w(0x2a), w(0x90), w(0x88),\ + w(0x46), w(0xee), w(0xb8), w(0x14), w(0xde), w(0x5e), w(0x0b), w(0xdb),\ + w(0xe0), w(0x32), w(0x3a), w(0x0a), w(0x49), w(0x06), w(0x24), w(0x5c),\ + w(0xc2), w(0xd3), w(0xac), w(0x62), w(0x91), w(0x95), w(0xe4), w(0x79),\ + w(0xe7), w(0xc8), w(0x37), w(0x6d), w(0x8d), w(0xd5), w(0x4e), w(0xa9),\ + w(0x6c), w(0x56), w(0xf4), w(0xea), w(0x65), w(0x7a), w(0xae), w(0x08),\ + w(0xba), w(0x78), w(0x25), w(0x2e), w(0x1c), w(0xa6), w(0xb4), w(0xc6),\ + w(0xe8), w(0xdd), w(0x74), w(0x1f), w(0x4b), w(0xbd), w(0x8b), w(0x8a),\ + w(0x70), w(0x3e), w(0xb5), w(0x66), w(0x48), w(0x03), w(0xf6), w(0x0e),\ + w(0x61), w(0x35), w(0x57), w(0xb9), w(0x86), w(0xc1), w(0x1d), w(0x9e),\ + w(0xe1), w(0xf8), w(0x98), w(0x11), w(0x69), w(0xd9), w(0x8e), w(0x94),\ + w(0x9b), w(0x1e), w(0x87), w(0xe9), w(0xce), w(0x55), w(0x28), w(0xdf),\ + w(0x8c), w(0xa1), w(0x89), w(0x0d), w(0xbf), w(0xe6), w(0x42), w(0x68),\ + w(0x41), w(0x99), w(0x2d), w(0x0f), w(0xb0), w(0x54), w(0xbb), w(0x16) } + +#define isb_data(w) { /* inverse S Box data values */ \ + w(0x52), w(0x09), w(0x6a), w(0xd5), w(0x30), w(0x36), w(0xa5), w(0x38),\ + w(0xbf), w(0x40), w(0xa3), w(0x9e), w(0x81), w(0xf3), w(0xd7), w(0xfb),\ + w(0x7c), w(0xe3), w(0x39), w(0x82), w(0x9b), w(0x2f), w(0xff), w(0x87),\ + w(0x34), w(0x8e), w(0x43), w(0x44), w(0xc4), w(0xde), w(0xe9), w(0xcb),\ + w(0x54), w(0x7b), w(0x94), w(0x32), w(0xa6), w(0xc2), w(0x23), w(0x3d),\ + w(0xee), w(0x4c), w(0x95), w(0x0b), w(0x42), w(0xfa), w(0xc3), w(0x4e),\ + w(0x08), w(0x2e), w(0xa1), w(0x66), w(0x28), w(0xd9), w(0x24), w(0xb2),\ + w(0x76), w(0x5b), w(0xa2), w(0x49), w(0x6d), w(0x8b), w(0xd1), w(0x25),\ + w(0x72), w(0xf8), w(0xf6), w(0x64), w(0x86), w(0x68), w(0x98), w(0x16),\ + w(0xd4), w(0xa4), w(0x5c), w(0xcc), w(0x5d), w(0x65), w(0xb6), w(0x92),\ + w(0x6c), w(0x70), w(0x48), w(0x50), w(0xfd), w(0xed), w(0xb9), w(0xda),\ + w(0x5e), w(0x15), w(0x46), w(0x57), w(0xa7), w(0x8d), w(0x9d), w(0x84),\ + w(0x90), w(0xd8), w(0xab), w(0x00), w(0x8c), w(0xbc), w(0xd3), w(0x0a),\ + w(0xf7), w(0xe4), w(0x58), w(0x05), w(0xb8), w(0xb3), w(0x45), w(0x06),\ + w(0xd0), w(0x2c), w(0x1e), w(0x8f), w(0xca), w(0x3f), w(0x0f), w(0x02),\ + w(0xc1), w(0xaf), w(0xbd), w(0x03), w(0x01), w(0x13), w(0x8a), w(0x6b),\ + w(0x3a), w(0x91), w(0x11), w(0x41), w(0x4f), w(0x67), w(0xdc), w(0xea),\ + w(0x97), w(0xf2), w(0xcf), w(0xce), w(0xf0), w(0xb4), w(0xe6), w(0x73),\ + w(0x96), w(0xac), w(0x74), w(0x22), w(0xe7), w(0xad), w(0x35), w(0x85),\ + w(0xe2), w(0xf9), w(0x37), w(0xe8), w(0x1c), w(0x75), w(0xdf), w(0x6e),\ + w(0x47), w(0xf1), w(0x1a), w(0x71), w(0x1d), w(0x29), w(0xc5), w(0x89),\ + w(0x6f), w(0xb7), w(0x62), w(0x0e), w(0xaa), w(0x18), w(0xbe), w(0x1b),\ + w(0xfc), w(0x56), w(0x3e), w(0x4b), w(0xc6), w(0xd2), w(0x79), w(0x20),\ + w(0x9a), w(0xdb), w(0xc0), w(0xfe), w(0x78), w(0xcd), w(0x5a), w(0xf4),\ + w(0x1f), w(0xdd), w(0xa8), w(0x33), w(0x88), w(0x07), w(0xc7), w(0x31),\ + w(0xb1), w(0x12), w(0x10), w(0x59), w(0x27), w(0x80), w(0xec), w(0x5f),\ + w(0x60), w(0x51), w(0x7f), w(0xa9), w(0x19), w(0xb5), w(0x4a), w(0x0d),\ + w(0x2d), w(0xe5), w(0x7a), w(0x9f), w(0x93), w(0xc9), w(0x9c), w(0xef),\ + w(0xa0), w(0xe0), w(0x3b), w(0x4d), w(0xae), w(0x2a), w(0xf5), w(0xb0),\ + w(0xc8), w(0xeb), w(0xbb), w(0x3c), w(0x83), w(0x53), w(0x99), w(0x61),\ + w(0x17), w(0x2b), w(0x04), w(0x7e), w(0xba), w(0x77), w(0xd6), w(0x26),\ + w(0xe1), w(0x69), w(0x14), w(0x63), w(0x55), w(0x21), w(0x0c), w(0x7d) } + +#define mm_data(w) { /* basic data for forming finite field tables */ \ + w(0x00), w(0x01), w(0x02), w(0x03), w(0x04), w(0x05), w(0x06), w(0x07),\ + w(0x08), w(0x09), w(0x0a), w(0x0b), w(0x0c), w(0x0d), w(0x0e), w(0x0f),\ + w(0x10), w(0x11), w(0x12), w(0x13), w(0x14), w(0x15), w(0x16), w(0x17),\ + w(0x18), w(0x19), w(0x1a), w(0x1b), w(0x1c), w(0x1d), w(0x1e), w(0x1f),\ + w(0x20), w(0x21), w(0x22), w(0x23), w(0x24), w(0x25), w(0x26), w(0x27),\ + w(0x28), w(0x29), w(0x2a), w(0x2b), w(0x2c), w(0x2d), w(0x2e), w(0x2f),\ + w(0x30), w(0x31), w(0x32), w(0x33), w(0x34), w(0x35), w(0x36), w(0x37),\ + w(0x38), w(0x39), w(0x3a), w(0x3b), w(0x3c), w(0x3d), w(0x3e), w(0x3f),\ + w(0x40), w(0x41), w(0x42), w(0x43), w(0x44), w(0x45), w(0x46), w(0x47),\ + w(0x48), w(0x49), w(0x4a), w(0x4b), w(0x4c), w(0x4d), w(0x4e), w(0x4f),\ + w(0x50), w(0x51), w(0x52), w(0x53), w(0x54), w(0x55), w(0x56), w(0x57),\ + w(0x58), w(0x59), w(0x5a), w(0x5b), w(0x5c), w(0x5d), w(0x5e), w(0x5f),\ + w(0x60), w(0x61), w(0x62), w(0x63), w(0x64), w(0x65), w(0x66), w(0x67),\ + w(0x68), w(0x69), w(0x6a), w(0x6b), w(0x6c), w(0x6d), w(0x6e), w(0x6f),\ + w(0x70), w(0x71), w(0x72), w(0x73), w(0x74), w(0x75), w(0x76), w(0x77),\ + w(0x78), w(0x79), w(0x7a), w(0x7b), w(0x7c), w(0x7d), w(0x7e), w(0x7f),\ + w(0x80), w(0x81), w(0x82), w(0x83), w(0x84), w(0x85), w(0x86), w(0x87),\ + w(0x88), w(0x89), w(0x8a), w(0x8b), w(0x8c), w(0x8d), w(0x8e), w(0x8f),\ + w(0x90), w(0x91), w(0x92), w(0x93), w(0x94), w(0x95), w(0x96), w(0x97),\ + w(0x98), w(0x99), w(0x9a), w(0x9b), w(0x9c), w(0x9d), w(0x9e), w(0x9f),\ + w(0xa0), w(0xa1), w(0xa2), w(0xa3), w(0xa4), w(0xa5), w(0xa6), w(0xa7),\ + w(0xa8), w(0xa9), w(0xaa), w(0xab), w(0xac), w(0xad), w(0xae), w(0xaf),\ + w(0xb0), w(0xb1), w(0xb2), w(0xb3), w(0xb4), w(0xb5), w(0xb6), w(0xb7),\ + w(0xb8), w(0xb9), w(0xba), w(0xbb), w(0xbc), w(0xbd), w(0xbe), w(0xbf),\ + w(0xc0), w(0xc1), w(0xc2), w(0xc3), w(0xc4), w(0xc5), w(0xc6), w(0xc7),\ + w(0xc8), w(0xc9), w(0xca), w(0xcb), w(0xcc), w(0xcd), w(0xce), w(0xcf),\ + w(0xd0), w(0xd1), w(0xd2), w(0xd3), w(0xd4), w(0xd5), w(0xd6), w(0xd7),\ + w(0xd8), w(0xd9), w(0xda), w(0xdb), w(0xdc), w(0xdd), w(0xde), w(0xdf),\ + w(0xe0), w(0xe1), w(0xe2), w(0xe3), w(0xe4), w(0xe5), w(0xe6), w(0xe7),\ + w(0xe8), w(0xe9), w(0xea), w(0xeb), w(0xec), w(0xed), w(0xee), w(0xef),\ + w(0xf0), w(0xf1), w(0xf2), w(0xf3), w(0xf4), w(0xf5), w(0xf6), w(0xf7),\ + w(0xf8), w(0xf9), w(0xfa), w(0xfb), w(0xfc), w(0xfd), w(0xfe), w(0xff) } + + +typedef bool aes_result; + +static const uint8_t sbox[256] = sb_data(f1); +static const uint8_t isbox[256] = isb_data(f1); + +static const uint8_t gfm2_sbox[256] = sb_data(f2); +static const uint8_t gfm3_sbox[256] = sb_data(f3); + +static const uint8_t gfmul_9[256] = mm_data(f9); +static const uint8_t gfmul_b[256] = mm_data(fb); +static const uint8_t gfmul_d[256] = mm_data(fd); +static const uint8_t gfmul_e[256] = mm_data(fe); + +typedef struct +{ + uint8_t ksch[(N_MAX_ROUNDS + 1) * N_BLOCK]; + uint8_t rnd; +}aes_context; + +class CAes +{ + public: + + CAes(); + + void aes_set_key( const uint8_t key[AES_KEY_SIZE] ); + aes_result aes_encrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK] ); + + // encryption functions + // \todo rewrite with class context + /* + aes_result aes_decrypt( const unsigned char in[N_BLOCK], unsigned char out[N_BLOCK], const aes_context ctx[1] ); + aes_result aes_cbc_encrypt(const unsigned char *in, unsigned char *out, unsigned long size, unsigned char iv[N_BLOCK], const aes_context ctx[1] ); + aes_result aes_cbc_decrypt(const unsigned char *in, unsigned char *out, unsigned long size, unsigned char iv[N_BLOCK], const aes_context ctx[1] ); + */ + + // helper functions + void xor_block( void *d, const void *s ); + + + private: + // context for this instance + aes_context context; + + // helper functions + void copy_and_key( void *d, const void *s, const void *k ); + void add_round_key( uint8_t d[N_BLOCK], const uint8_t k[N_BLOCK] ); + void shift_sub_rows( uint8_t st[N_BLOCK] ); + void inv_shift_sub_rows( uint8_t st[N_BLOCK] ); + void mix_sub_columns( uint8_t dt[N_BLOCK] ); + void inv_mix_sub_columns( uint8_t dt[N_BLOCK] ); +}; From f8b301be35bdc2847cb18f3943357e0ca936feb7 Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 14 Nov 2019 18:37:22 +0100 Subject: [PATCH 10/44] decoding gpdf commissioning payload --- .../gpd-commissioning-command-payload.cpp | 166 ++++++++++++++++++ .../gpd-commissioning-command-payload.h | 149 ++++++++++++++++ 2 files changed, 315 insertions(+) create mode 100644 src/domain/zbmessage/gpd-commissioning-command-payload.cpp create mode 100644 src/domain/zbmessage/gpd-commissioning-command-payload.h diff --git a/src/domain/zbmessage/gpd-commissioning-command-payload.cpp b/src/domain/zbmessage/gpd-commissioning-command-payload.cpp new file mode 100644 index 00000000..d7aa4f36 --- /dev/null +++ b/src/domain/zbmessage/gpd-commissioning-command-payload.cpp @@ -0,0 +1,166 @@ +/** + * @file gpd-commissioning-payload.cpp + * + * @brief + */ + +#include +#include +#include + +#include "../byte-manip.h" +#include "../custom-aes.h" +#include "gpd-commissioning-command-payload.h" + +/** + * @brief Construction from an incoming ezsp raw message + * + * @param raw_message The buffer to construct from + */ +CGpdCommissioningPayload::CGpdCommissioningPayload(const std::vector& raw_message, uint32_t i_src_id): + device_id(raw_message.at(0)), + options(raw_message.at(1)), + extended_options(0), + key(), + key_mic(), + out_frame_counter(), + app_information(0), + manufacturer_id(), + model_id(), + gpd_command_list(), + gpd_cluster_list() +{ + // only device_id and option are mandatory, other field depend of option value + uint8_t l_idx = 2; + + // extended option + if( options & (1<(device_id) << "]"; + buf << "[options : "<< std::hex << std::setw(2) << std::setfill('0') << static_cast(options) << "]"; + buf << "[extended_options : "<< std::hex << std::setw(2) << std::setfill('0') << static_cast(extended_options) << "]"; + buf << "[key : "; + for(uint8_t loop=0; loop(key[loop]); } + buf << "]"; + buf << "[key_mic : "<< std::hex << std::setw(8) << std::setfill('0') << static_cast(key_mic) << "]"; + buf << "[out_frame_counter : "<< std::hex << std::setw(8) << std::setfill('0') << static_cast(out_frame_counter) << "]"; + buf << "[app_information : "<< std::hex << std::setw(2) << std::setfill('0') << static_cast(app_information) << "]"; + buf << "[manufacturer_id : "<< std::hex << std::setw(4) << std::setfill('0') << static_cast(manufacturer_id) << "]"; + buf << "[model_id : "<< std::hex << std::setw(4) << std::setfill('0') << static_cast(model_id) << "]"; + buf << "[gpd_command_list :"; + for(uint8_t loop=0; loop(gpd_command_list[loop]); } + buf << "]"; + buf << "[gpd_cluster_list :"; + for(uint8_t loop=0; loop(gpd_cluster_list[loop]); } + buf << "]"; + buf << " }"; + + return buf.str(); +} + +std::ostream& operator<< (std::ostream& out, const CGpdCommissioningPayload& data){ + out << data.String(); + return out; +} \ No newline at end of file diff --git a/src/domain/zbmessage/gpd-commissioning-command-payload.h b/src/domain/zbmessage/gpd-commissioning-command-payload.h new file mode 100644 index 00000000..01106eb9 --- /dev/null +++ b/src/domain/zbmessage/gpd-commissioning-command-payload.h @@ -0,0 +1,149 @@ +/** + * @file gpd-commissionning-command-payload.h + * + * @brief decoding payload of gpd commissioning command according to A.4.2.1.1 GPD Commissioning command from docs-14-0563-16-batt-green-power-spec_ProxyBasic.pdf + */ +#pragma once + +#include +#include + +#include "../ezsp-protocol/ezsp-enum.h" + +// option bitfield +#define COM_OPTION_MAC_SEQ_CAPABILITY_BIT 0 +#define COM_OPTION_RX_ON_CAPABILITY_BIT 1 +#define COM_OPTION_APPLICATION_INFORMATION_BIT 2 +#define COM_OPTION_PAN_ID_REQUEST_BIT 4 +#define COM_OPTION_GP_SECURITY_KEY_REQUEST_BIT 5 +#define COM_OPTION_FIXED_LOCATION_BIT 6 +#define COM_OPTION_EXTENDED_OPTION_FIELD_BIT 7 + +// extend option bitfield +#define COM_EXT_OPTION_SECURITY_LVL_CAPABILITY_BIT 0 +#define COM_EXT_OPTION_KEY_TYPE_BIT 2 +#define COM_EXT_OPTION_GPD_KEY_PRESENT_BIT 5 +#define COM_EXT_OPTION_GPD_KEY_ENCRYPTION_BIT 6 +#define COM_EXT_OPTION_GPD_OUT_COUNTER_PRESENT_BIT 7 + +// application information bitfield +#define COM_APP_INFO_MANUFACTURER_ID_PRESENT_BIT 0 +#define COM_APP_INFO_MODEL_ID_PRESENT_BIT 1 +#define COM_APP_INFO_GPD_COMMANDS_PRESENT_BIT 2 +#define COM_APP_INFO_CLUSTER_LIST_PRESENT_BIT 3 + +class CGpdCommissioningPayload +{ + public: + + /** + * @brief Default constructor + * + * Construction without arguments is not allowed + */ + CGpdCommissioningPayload(); // = delete; + + /** + * @brief Assignment operator + * + * Copy construction is forbidden on this class + */ + CGpdCommissioningPayload& operator=(const CGpdCommissioningPayload& other) = delete; + + /** + * @brief Construction from an incoming ezsp raw message + * + * @param raw_message The buffer to construct from + * @param i_src_id source id of gpd frame, use to decrypt key + */ + CGpdCommissioningPayload(const std::vector& raw_message, uint32_t i_src_id); + + /** + * @brief Getter key + * + * @return key + */ + EmberKeyData getKey(){ return key; } + + /** + * @brief Getter + * + * @return deviceId + */ + uint8_t getDeviceId(){ return device_id; } + + /** + * @brief Getter + * + * @return extended_options + */ + uint8_t getExtendedOption(){ return extended_options; } + + /** + * @brief Getter + * + * @return out_frame_counter + */ + uint32_t getOutFrameCounter(){ return out_frame_counter; } + + + /** + * @brief Dump this instance as a string + * + * @return The resulting string + */ + std::string String() const; + + /** + * @brief Serialize to an iostream + * + * @param out The original output stream + * @param data The object to serialize + * + * @return The new output stream with serialized data appended + */ + friend std::ostream& operator<< (std::ostream& out, const CGpdCommissioningPayload& data); + + private: + // define in ZigBee document 13-0166, Master List of Green Power Device Definitions, revision 00 or later + uint8_t device_id; + // bits field: + // b0 : MACsequenceNumberCapability (0b1:incremental MAC sequence number, 0b0:random MAC sequence number) + // b1 : RxOnCapability (0b1:GPD has receiving capabilities in operational mode.) + // b2 : Application information present + // b3 : reserved + // b4 : PANId request + // b5 : GP Security Key request + // b6 : FixedLocation + // b7 : Extended Options Field + uint8_t options; + // bits field: + // b0-1 : SecurityLevelCapabilities (0b00:No security, 0b01:Reserved, 0b10:4B frame counter and 4B MIC Only, 0b11:Encryption & 4B frame counter and 4B MIC) + // b2-4 : KeyType : (see A.3.7.1.2 gpSecurityKeyType) + // 0b000 : no key + // 0b001 : ZigBee NWK key + // 0b010 : GPD group key + // 0b011 : NWK-key derived GPD group key + // 0b100 : (individual) outof-the-box GPD key + // 0b101-0b110 : Reserved + // 0b111 : Derived individual GPD key + // b5 : GPD Key present + // b6 : GPD Key encryption + // b7 : GPD outgoing counter present + uint8_t extended_options; + + EmberKeyData key; + uint32_t key_mic; + uint32_t out_frame_counter; + // bits field: + // b0 : ManufacturerID present + // b1 : ModelID present + // b2 : GPD commands present + // b3 : Cluster list present + // b4-7 : reserved + uint8_t app_information; + uint16_t manufacturer_id; + uint16_t model_id; + std::vector gpd_command_list; + std::vector gpd_cluster_list; +}; \ No newline at end of file From fa8ae12db080c113c8a65aba5a763eec77f7bae3 Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 14 Nov 2019 18:37:50 +0100 Subject: [PATCH 11/44] use gpdf decoding function, remove harcoded key --- src/domain/zigbee-tools/green-power-sink.cpp | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/domain/zigbee-tools/green-power-sink.cpp b/src/domain/zigbee-tools/green-power-sink.cpp index 75eda0b6..bcc91d6e 100644 --- a/src/domain/zigbee-tools/green-power-sink.cpp +++ b/src/domain/zigbee-tools/green-power-sink.cpp @@ -14,6 +14,8 @@ #include "../byte-manip.h" #include "../../domain/zbmessage/zigbee-message.h" +#include "../../domain/zbmessage/gpd-commissioning-command-payload.h" + #include "../../spi/GenericLogger.h" #include "../../spi/ILogger.h" @@ -211,15 +213,23 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re { if( SINK_COM_IN_PROGRESS == sink_state ) { + // decode payload + CGpdCommissioningPayload l_payload(gpf_comm_frame.getPayload(),gpf_comm_frame.getSourceId()); + + // debug + clogD << "GPD Commissioning payload : " << l_payload << std::endl; + // construct sink table entry + /* EmberKeyData l_harcoded_key{0x59, 0x13, 0x29, 0x50, 0x28, 0x9D, 0x14, 0xFD, - 0x73, 0xF9, 0xC3, 0x25, 0xD4, 0x57, 0xAB, 0xB5}; + 0x73, 0xF9, 0xC3, 0x25, 0xD4, 0x57, 0xAB, 0xB5};*/ CEmberGpAddressStruct l_gpd_addr(gpf_comm_frame.getSourceId()); - CEmberGpSinkTableEntryStruct l_entry(0x01, l_gpd_addr, gpf_comm_frame.getPayload().at(0), - static_cast(gpf_comm_frame.getSourceId()&0xFFFF), 0x12, - quad_u8_to_u32(gpf_comm_frame.getPayload().at(23),gpf_comm_frame.getPayload().at(24),gpf_comm_frame.getPayload().at(25),gpf_comm_frame.getPayload().at(26)), - l_harcoded_key ); + CEmberGpSinkTableEntryStruct l_entry(0x01, l_gpd_addr, l_payload.getDeviceId(), + static_cast(gpf_comm_frame.getSourceId()&0xFFFF), + l_payload.getExtendedOption()&0x1F, + l_payload.getOutFrameCounter(), + l_payload.getKey() ); // call gpSinkSetEntry(0,l_entry); From b0699ad6a69a782ef4ad276dbbc0699bbb1ff142 Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 14 Nov 2019 18:38:06 +0100 Subject: [PATCH 12/44] add new files to build --- src/libezsp.mk.inc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/libezsp.mk.inc b/src/libezsp.mk.inc index 526948c8..0282d085 100644 --- a/src/libezsp.mk.inc +++ b/src/libezsp.mk.inc @@ -1,8 +1,10 @@ LIBEZSP_COMMON_SRC = \ $(SRC_DOMAIN_PATH)/ezsp-dongle.cpp \ $(SRC_DOMAIN_PATH)/ash.cpp \ + $(SRC_DOMAIN_PATH)/custom-aes.cpp \ $(SRC_DOMAIN_PATH)/zbmessage/green-power-frame.cpp \ $(SRC_DOMAIN_PATH)/zbmessage/green-power-sink-table-entry.cpp \ + $(SRC_DOMAIN_PATH)/zbmessage/gpd-commissioning-command-payload.cpp \ $(SRC_DOMAIN_PATH)/zbmessage/zigbee-message.cpp \ $(SRC_DOMAIN_PATH)/zbmessage/zclheader.cpp \ $(SRC_DOMAIN_PATH)/zbmessage/zclframecontrol.cpp \ From 72da229ce28267b3755994c9f4560b96731c5602 Mon Sep 17 00:00:00 2001 From: seb Date: Fri, 15 Nov 2019 11:09:20 +0100 Subject: [PATCH 13/44] adding class to simplify usage of options field of gp sink table entry --- .../ember-gp-sink-table-entry-struct.cpp | 4 +- .../struct/ember-gp-sink-table-entry-struct.h | 3 +- .../ember-gp-sink-table-options-field.cpp | 45 ++++++++++++ .../ember-gp-sink-table-options-field.h | 68 +++++++++++++++++++ src/libezsp.mk.inc | 1 + 5 files changed, 118 insertions(+), 3 deletions(-) create mode 100644 src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp create mode 100644 src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp index 9cec0931..96d38357 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp @@ -80,8 +80,8 @@ std::vector CEmberGpSinkTableEntryStruct::getRaw(void) // Internal status of the sink table entry. l_struct.push_back(status); // 0x01 : active, 0xff : disable // The tunneling options (this contains both options and extendedOptions from the spec). WARNING 16 bits !!! - l_struct.push_back(u16_get_lo_u8(options)); - l_struct.push_back(u16_get_hi_u8(options)); + l_struct.push_back(u16_get_lo_u8(options.get())); + l_struct.push_back(u16_get_hi_u8(options.get())); // The addressing info of the GPD. std::vector l_addr = gpd.getRaw(); l_struct.insert(l_struct.end(), l_addr.begin(), l_addr.end()); diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h index f3c9920f..902495bd 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h @@ -8,6 +8,7 @@ #include "../ezsp-enum.h" #include "ember-gp-address-struct.h" +#include "ember-gp-sink-table-options-field.h" #ifdef USE_RARITAN /**** Start of the official API; no includes below this point! ***************/ @@ -83,7 +84,7 @@ class CEmberGpSinkTableEntryStruct // Internal status of the sink table entry. EmberGpSinkTableEntryStatus status; // The tunneling options (this contains both options and extendedOptions from the spec). WRONG Specification only 16 bits like option without extended ... - uint16_t options; + CEmberGpSinkTableOption options; // The addressing info of the GPD. CEmberGpAddressStruct gpd; // The device id for the GPD. diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp new file mode 100644 index 00000000..ab6c8248 --- /dev/null +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp @@ -0,0 +1,45 @@ + +/** +* @brief Details of options bit filed for sink table entry +*/ + +#include "ember-gp-sink-table-options-field.h" + +/** + * raw constructor + * - bits 0..2 : Application Id (0b000 : use source Id) + * - bits 3..4 : Communication mode (0b01 : groupcast forwarding of the GP Notification command to DGroupID) + * - bit 5 : Sequence number capabilities (0b1 : use incremental sequence number) + * - bit 6 : RxOnCapability (0b0 : not capable) + * - bit 7 : FixedLocation (0b1 : not a mobile device) + * - bit 8 : AssignedAlias (0b0 : the derived alias is used) + * - bit 9 : Security use (0b1 : indicates that security-related parameters of the Sink Table entry are present) + * - bit 10..15 : Reserved + */ +CEmberGpSinkTableOption::CEmberGpSinkTableOption(const uint16_t i_options) : + application_id(static_cast(i_options&0x7)), + communication_mode(static_cast((i_options>>3)&0x3)), + sequence_number_capabilities((i_options&0x20)!=0), + rx_on_capability((i_options&0x40)!=0), + fixed_location((i_options&0x80)!=0), + assigned_alias((i_options&0x100)!=0), + security_use((i_options&0x200)!=0) +{ +} + +/** + * raw getter + */ +uint16_t CEmberGpSinkTableOption::get(void) +{ + uint16_t o_options = 0 + \ + application_id + \ + (communication_mode<<3) + \ + (sequence_number_capabilities<<5) + \ + (rx_on_capability<<6) + \ + (fixed_location<<7) + \ + (assigned_alias<<8) + \ + (security_use<<9); + + return o_options; +} diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h new file mode 100644 index 00000000..710ad7d8 --- /dev/null +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h @@ -0,0 +1,68 @@ +/** +* @brief Details of options bit filed for sink table entry +* option : 0x02A8 (cf. A3.3.2.2.1 Options parameter of the Sink Table from doc doc-14-0563-16-batt-green-power-spec_ProxyBasic.pdf) +* - bits 0..2 : Application Id (0b000 : use source Id) +* - bits 3..4 : Communication mode (0b01 : groupcast forwarding of the GP Notification command to DGroupID) +* - bit 5 : Sequence number capabilities (0b1 : use incremental sequence number) +* - bit 6 : RxOnCapability (0b0 : not capable) +* - bit 7 : FixedLocation (0b1 : not a mobile device) +* - bit 8 : AssignedAlias (0b0 : the derived alias is used) +* - bit 9 : Security use (0b1 : indicates that security-related parameters of the Sink Table entry are present) +* - bit 10..15 : Reserved +*/ + +#pragma once + +#include +#include "../ezsp-enum.h" + +#ifdef USE_RARITAN +/**** Start of the official API; no includes below this point! ***************/ +#include +#endif // USE_RARITAN + +class CEmberGpSinkTableOption +{ + public: + /** + * @brief Default constructor + * + * Construction without arguments is not allowed + */ + CEmberGpSinkTableOption() = delete; + + /** + * @brief Copy constructor + * + * Copy construction is forbidden on this class + */ + CEmberGpSinkTableOption(const CEmberGpSinkTableOption& other) = delete; + + /** + * @brief Assignment operator + * + * Assignment is forbidden on this class + */ + CEmberGpSinkTableOption& operator=(const CEmberGpSinkTableOption& other) = delete; + + + /** + * raw constructor + */ + CEmberGpSinkTableOption(const uint16_t i_options); + + /** + * raw getter + */ + uint16_t get(void); + + + private: + uint8_t application_id; + uint8_t communication_mode; + bool sequence_number_capabilities; + bool rx_on_capability; + bool fixed_location; + bool assigned_alias; + bool security_use; +}; \ No newline at end of file diff --git a/src/libezsp.mk.inc b/src/libezsp.mk.inc index 0282d085..7b07a227 100644 --- a/src/libezsp.mk.inc +++ b/src/libezsp.mk.inc @@ -18,6 +18,7 @@ LIBEZSP_COMMON_SRC = \ $(SRC_DOMAIN_PATH)/ezsp-protocol/struct/ember-child-data-struct.cpp \ $(SRC_DOMAIN_PATH)/ezsp-protocol/struct/ember-gp-address-struct.cpp \ $(SRC_DOMAIN_PATH)/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp \ + $(SRC_DOMAIN_PATH)/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp \ $(SRC_DOMAIN_PATH)/zigbee-tools/zigbee-networking.cpp \ $(SRC_DOMAIN_PATH)/zigbee-tools/zigbee-messaging.cpp \ $(SRC_DOMAIN_PATH)/zigbee-tools/green-power-sink.cpp \ From 3f313600ac6b5212f09905def348481ebc06db29 Mon Sep 17 00:00:00 2001 From: seb Date: Fri, 15 Nov 2019 15:05:08 +0100 Subject: [PATCH 14/44] adding some setter/getter --- .../struct/ember-gp-address-struct.cpp | 24 ++++++ .../struct/ember-gp-address-struct.h | 15 +++- .../ember-gp-sink-table-entry-struct.cpp | 38 ++++++++- .../struct/ember-gp-sink-table-entry-struct.h | 59 ++++++++++++- .../ember-gp-sink-table-options-field.cpp | 84 ++++++++++++++++++- .../ember-gp-sink-table-options-field.h | 79 +++++++++++++++-- .../gpd-commissioning-command-payload.h | 22 ++++- 7 files changed, 304 insertions(+), 17 deletions(-) diff --git a/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp b/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp index d9cc9e43..51bed758 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp +++ b/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp @@ -27,6 +27,30 @@ CEmberGpAddressStruct::CEmberGpAddressStruct(const std::vector& raw_mes { } +/** + * This method is a friend of CAPSFrame class + * swap() is needed within operator=() to implement to copy and swap paradigm +**/ +void swap(CEmberGpAddressStruct& first, CEmberGpAddressStruct& second) /* nothrow */ +{ + using std::swap; // Enable ADL + + swap(first.gpdIeeeAddress, second.gpdIeeeAddress); + swap(first.applicationId, second.applicationId); + swap(first.endpoint, second.endpoint); + /* Once we have swapped the members of the two instances... the two instances have actually been swapped */ +} + +/** + * @brief Assignment operator + */ +CEmberGpAddressStruct& CEmberGpAddressStruct::operator=(CEmberGpAddressStruct other) +{ + swap(*this, other); + return *this; +} + + CEmberGpAddressStruct::CEmberGpAddressStruct(const uint32_t i_srcId): gpdIeeeAddress(), /* FIXME */ applicationId(0), diff --git a/src/domain/ezsp-protocol/struct/ember-gp-address-struct.h b/src/domain/ezsp-protocol/struct/ember-gp-address-struct.h index 6512c4b2..744108a4 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-address-struct.h +++ b/src/domain/ezsp-protocol/struct/ember-gp-address-struct.h @@ -40,11 +40,20 @@ class CEmberGpAddressStruct CEmberGpAddressStruct(const uint32_t i_srcId); /** - * @brief Assignment operator + * @brief swap function to allow implementing of copy-and-swap idiom on members of type CEmberGpSinkTableOption + * + * This function will swap all attributes of \p first and \p second + * See http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom * - * Copy construction is forbidden on this class + * @param first The first object + * @param second The second object + */ + friend void (::swap)(CEmberGpAddressStruct& first, CEmberGpAddressStruct& second); + + /** + * @brief Assignment operator */ - CEmberGpAddressStruct& operator=(const CEmberGpAddressStruct& other) = delete; + CEmberGpAddressStruct& operator=(CEmberGpAddressStruct other); /** * @brief The GPD's EUI64. diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp index 96d38357..74bb3a6a 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp @@ -42,6 +42,7 @@ CEmberGpSinkTableEntryStruct::CEmberGpSinkTableEntryStruct(const std::vector CEmberGpSinkTableEntryStruct::getRaw(void) l_struct.insert(l_struct.end(), gpd_key.begin(), gpd_key.end()); return l_struct; +} + + +std::string CEmberGpSinkTableEntryStruct::String() const +{ + std::stringstream buf; + + buf << "CEmberGpSinkTableEntryStruct : { "; + buf << "[status : "<< std::hex << std::setw(2) << std::setfill('0') << unsigned(status) << "]"; + buf << "[options : "<< options << "]"; + buf << "[gpd : "<< gpd << "]"; + buf << "[device_id : "<< std::hex << std::setw(2) << std::setfill('0') << unsigned(device_id) << "]"; + buf << "[sink_list[0] :"; + for(uint8_t loop=0; loop getRaw(void); + /** + * @brief status setter + */ + void setEntryActive(bool i_active){ i_active?status=0x01:status=0xFF; } + + /** + * @brief options setter + */ + void setOptions(CEmberGpSinkTableOption i_options){ options=i_options; } + + /** + * @brief gpd setter + */ + void setGpdAddress(CEmberGpAddressStruct i_gpd_address){ gpd=i_gpd_address; } + + /** + * @brief device_id setter + */ + void setDeviceId(uint8_t i_device_id){ device_id=i_device_id; } + + /** + * @brief assigned_alias setter + */ + void setAlias(uint16_t i_alias){ assigned_alias=i_alias; } + + /** + * @brief security_options setter + */ + void setSecurityOption(uint8_t i_security_option){ security_options=i_security_option; } + + /** + * @brief gpdSecurity_frame_counter setter + */ + void setFrameCounter(EmberGpSecurityFrameCounter i_frm_counter){ gpdSecurity_frame_counter=i_frm_counter; } + + /** + * @brief gpd_key setter + */ + void setKey(EmberKeyData i_gpd_key){ gpd_key=i_gpd_key; } + + /** + * @brief Dump this instance as a string + * + * @return The resulting string + */ + std::string String() const; + + /** + * @brief Serialize to an iostream + * + * @param out The original output stream + * @param data The object to serialize + * + * @return The new output stream with serialized data appended + */ + friend std::ostream& operator<< (std::ostream& out, const CEmberGpSinkTableEntryStruct& data); private: // Internal status of the sink table entry. diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp index ab6c8248..5f8220d9 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp @@ -1,10 +1,28 @@ - /** * @brief Details of options bit filed for sink table entry */ +#include +#include + #include "ember-gp-sink-table-options-field.h" +/** + * @brief Copy constructor + */ +CEmberGpSinkTableOption::CEmberGpSinkTableOption(const CEmberGpSinkTableOption& other) : + application_id(other.application_id), + communication_mode(other.communication_mode), + sequence_number_capabilities(other.sequence_number_capabilities), + rx_on_capability(other.rx_on_capability), + fixed_location(other.fixed_location), + assigned_alias(other.assigned_alias), + security_use(other.security_use) +{ + +} + + /** * raw constructor * - bits 0..2 : Application Id (0b000 : use source Id) @@ -27,6 +45,48 @@ CEmberGpSinkTableOption::CEmberGpSinkTableOption(const uint16_t i_options) : { } +/** + * @brief constructor from commissioning payload option and more + * + * @param i_application_id : application id meeans way to address gpd : by sourceid or ieee + * @param i_gpdf_commissioning_payload : permit to know capability of gpd + */ +CEmberGpSinkTableOption::CEmberGpSinkTableOption(const uint8_t i_application_id, CGpdCommissioningPayload i_gpdf_commissioning_payload) : + application_id(i_application_id), + communication_mode(1), + sequence_number_capabilities(i_gpdf_commissioning_payload.isMACsequenceNumberCapability()), + rx_on_capability(i_gpdf_commissioning_payload.isRxOnCapability()), + fixed_location(i_gpdf_commissioning_payload.isFixedLocation()), + assigned_alias(0), + security_use(i_gpdf_commissioning_payload.isExtendedOptionsFieldPresent()) +{ + +} + +/** + * This method is a friend of CAPSFrame class + * swap() is needed within operator=() to implement to copy and swap paradigm +**/ +void swap(CEmberGpSinkTableOption& first, CEmberGpSinkTableOption& second) /* nothrow */ +{ + using std::swap; // Enable ADL + + swap(first.application_id, second.application_id); + swap(first.communication_mode, second.communication_mode); + swap(first.sequence_number_capabilities, second.sequence_number_capabilities); + swap(first.rx_on_capability, second.rx_on_capability); + swap(first.fixed_location, second.fixed_location); + swap(first.assigned_alias, second.assigned_alias); + swap(first.security_use, second.security_use); + /* Once we have swapped the members of the two instances... the two instances have actually been swapped */ +} + +CEmberGpSinkTableOption& CEmberGpSinkTableOption::operator=( CEmberGpSinkTableOption other) +{ + swap(*this, other); + return *this; +} + /** * raw getter */ @@ -43,3 +103,25 @@ uint16_t CEmberGpSinkTableOption::get(void) return o_options; } + +std::string CEmberGpSinkTableOption::String() const +{ + std::stringstream buf; + + buf << "CEmberGpSinkTableOption : { "; + buf << "[application_id : "<< std::hex << std::setw(2) << std::setfill('0') << unsigned(application_id) << "]"; + buf << "[communication_mode : "<< std::hex << std::setw(2) << std::setfill('0') << unsigned(communication_mode) << "]"; + buf << "[sequence_number_capabilities : "<< std::hex << std::setw(2) << std::setfill('0') << unsigned(sequence_number_capabilities) << "]"; + buf << "[rx_on_capability : "<< std::hex << std::setw(2) << std::setfill('0') << unsigned(rx_on_capability) << "]"; + buf << "[fixed_location : "<< std::hex << std::setw(2) << std::setfill('0') << unsigned(fixed_location) << "]"; + buf << "[assigned_alias : "<< std::hex << std::setw(2) << std::setfill('0') << unsigned(assigned_alias) << "]"; + buf << "[security_use : "<< std::hex << std::setw(2) << std::setfill('0') << unsigned(security_use) << "]"; + buf << " }"; + + return buf.str(); +} + +std::ostream& operator<< (std::ostream& out, const CEmberGpSinkTableOption& data){ + out << data.String(); + return out; +} \ No newline at end of file diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h index 710ad7d8..b3a952d1 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h @@ -15,6 +15,7 @@ #include #include "../ezsp-enum.h" +#include "../../zbmessage/gpd-commissioning-command-payload.h" // BAD DEPENDANCY NEED TO BE INPROVE #ifdef USE_RARITAN /**** Start of the official API; no includes below this point! ***************/ @@ -33,30 +34,90 @@ class CEmberGpSinkTableOption /** * @brief Copy constructor - * - * Copy construction is forbidden on this class */ - CEmberGpSinkTableOption(const CEmberGpSinkTableOption& other) = delete; + CEmberGpSinkTableOption(const CEmberGpSinkTableOption& other); /** * @brief Assignment operator - * - * Assignment is forbidden on this class */ - CEmberGpSinkTableOption& operator=(const CEmberGpSinkTableOption& other) = delete; + CEmberGpSinkTableOption& operator=( CEmberGpSinkTableOption other); + /** + * @brief swap function to allow implementing of copy-and-swap idiom on members of type CEmberGpSinkTableOption + * + * This function will swap all attributes of \p first and \p second + * See http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom + * + * @param first The first object + * @param second The second object + */ + friend void (::swap)(CEmberGpSinkTableOption& first, CEmberGpSinkTableOption& second); /** - * raw constructor + * @brief raw constructor */ CEmberGpSinkTableOption(const uint16_t i_options); /** - * raw getter + * @brief constructor from commissioning payload option and more + * + * @param i_application_id : application id meeans way to address gpd : by sourceid or ieee + * @param i_gpdf_commissioning_option : permit to know capability of gpd + */ + CEmberGpSinkTableOption(const uint8_t i_application_id, CGpdCommissioningPayload i_gpdf_commissioning_payload); + + /** + * @brief raw getter */ uint16_t get(void); - + /** + * @brief application_id getter + */ + uint8_t getApplicationId(void){ return application_id; } + /** + * @brief communication_mode getter + */ + uint8_t getCommunicationMode(void){ return communication_mode; } + /** + * @brief sequence_number_capabilities getter + */ + bool isSequenceNumberCapabilities(void){ return sequence_number_capabilities; } + /** + * @brief rx_on_capability getter + */ + bool isRxOnCapability(void){ return rx_on_capability; } + /** + * @brief fixed_location getter + */ + bool isFixedLocation(void){ return fixed_location; } + /** + * @brief assigned_alias getter + */ + bool isAssignedAlias(void){ return assigned_alias; } + /** + * @brief security_use getter + */ + bool isSecurityUse(void){ return security_use; } + + + /** + * @brief Dump this instance as a string + * + * @return The resulting string + */ + std::string String() const; + + /** + * @brief Serialize to an iostream + * + * @param out The original output stream + * @param data The object to serialize + * + * @return The new output stream with serialized data appended + */ + friend std::ostream& operator<< (std::ostream& out, const CEmberGpSinkTableOption& data); + private: uint8_t application_id; uint8_t communication_mode; diff --git a/src/domain/zbmessage/gpd-commissioning-command-payload.h b/src/domain/zbmessage/gpd-commissioning-command-payload.h index 01106eb9..908b27a2 100644 --- a/src/domain/zbmessage/gpd-commissioning-command-payload.h +++ b/src/domain/zbmessage/gpd-commissioning-command-payload.h @@ -41,7 +41,7 @@ class CGpdCommissioningPayload * * Construction without arguments is not allowed */ - CGpdCommissioningPayload(); // = delete; + CGpdCommissioningPayload() = delete; /** * @brief Assignment operator @@ -72,6 +72,26 @@ class CGpdCommissioningPayload */ uint8_t getDeviceId(){ return device_id; } + // bits field: + // b0 : MACsequenceNumberCapability (0b1:incremental MAC sequence number, 0b0:random MAC sequence number) + // b1 : RxOnCapability (0b1:GPD has receiving capabilities in operational mode.) + // b2 : Application information present + // b3 : reserved + // b4 : PANId request + // b5 : GP Security Key request + // b6 : FixedLocation + // b7 : Extended Options Field + /** + * @brief options getters bit field + */ + bool isMACsequenceNumberCapability(){ return (options & (1< Date: Fri, 15 Nov 2019 15:05:55 +0100 Subject: [PATCH 15/44] remove some harcoded value --- src/domain/zigbee-tools/green-power-sink.cpp | 51 +++++++++++++++----- src/domain/zigbee-tools/green-power-sink.h | 2 + 2 files changed, 40 insertions(+), 13 deletions(-) diff --git a/src/domain/zigbee-tools/green-power-sink.cpp b/src/domain/zigbee-tools/green-power-sink.cpp index bcc91d6e..7b3a030b 100644 --- a/src/domain/zigbee-tools/green-power-sink.cpp +++ b/src/domain/zigbee-tools/green-power-sink.cpp @@ -66,6 +66,7 @@ CGpSink::CGpSink( CEzspDongle &i_dongle, CZigbeeMessaging &i_zb_messaging ) : sink_table(), sink_state(SINK_NOT_INIT), gpf_comm_frame(), + sink_table_index(0xFF), observers() { dongle.registerObserver(this); @@ -203,8 +204,23 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re { if( SINK_COM_IN_PROGRESS == sink_state ) { - // retrieve entry - gpSinkGetEntry( i_msg_receive.at(0) ); + // save allocate index + sink_table_index = i_msg_receive.at(0); + + // debug + clogD << "EZSP_GP_SINK_TABLE_FIND_OR_ALLOCATE_ENTRY response index : " << std::hex << std::setw(2) << std::setfill('0') << sink_table_index << std::endl; + + // retrieve entry at selected index + if( 0xFF != sink_table_index ) + { + gpSinkGetEntry( sink_table_index ); + } + else + { + // no place to done pairing : FAILED + clogD << "INVALID SINK TABLE ENTRY, PAIRING FAILED !!" << std::endl; + setSinkState(SINK_READY); + } } } break; @@ -213,27 +229,36 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re { if( SINK_COM_IN_PROGRESS == sink_state ) { + EEmberStatus l_status = static_cast(i_msg_receive.at(0)); + CEmberGpSinkTableEntryStruct l_entry({i_msg_receive.begin()+1,i_msg_receive.end()}); + + // debug + clogD << "EZSP_GP_SINK_TABLE_GET_ENTRY Response status :" << CEzspEnum::EEmberStatusToString(l_status) << ", table entry : " << l_entry << std::endl; + // decode payload CGpdCommissioningPayload l_payload(gpf_comm_frame.getPayload(),gpf_comm_frame.getSourceId()); // debug clogD << "GPD Commissioning payload : " << l_payload << std::endl; - // construct sink table entry - /* - EmberKeyData l_harcoded_key{0x59, 0x13, 0x29, 0x50, 0x28, 0x9D, 0x14, 0xFD, - 0x73, 0xF9, 0xC3, 0x25, 0xD4, 0x57, 0xAB, 0xB5};*/ + // update sink table entry CEmberGpAddressStruct l_gpd_addr(gpf_comm_frame.getSourceId()); + CEmberGpSinkTableOption l_options(l_gpd_addr.getApplicationId(),l_payload); - CEmberGpSinkTableEntryStruct l_entry(0x01, l_gpd_addr, l_payload.getDeviceId(), - static_cast(gpf_comm_frame.getSourceId()&0xFFFF), - l_payload.getExtendedOption()&0x1F, - l_payload.getOutFrameCounter(), - l_payload.getKey() ); + l_entry.setEntryActive(true); + l_entry.setOptions(l_options); + l_entry.setGpdAddress(l_gpd_addr); + l_entry.setDeviceId(l_payload.getDeviceId()); + l_entry.setAlias(static_cast(gpf_comm_frame.getSourceId()&0xFFFF)); + l_entry.setSecurityOption(l_payload.getExtendedOption()&0x1F); + l_entry.setFrameCounter(l_payload.getOutFrameCounter()); + l_entry.setKey(l_payload.getKey()); - // call - gpSinkSetEntry(0,l_entry); + // debug + clogD << "Update table entry : " << l_entry << std::endl; + // call + gpSinkSetEntry(sink_table_index,l_entry); } } break; diff --git a/src/domain/zigbee-tools/green-power-sink.h b/src/domain/zigbee-tools/green-power-sink.h index 1716929f..627cfcd3 100644 --- a/src/domain/zigbee-tools/green-power-sink.h +++ b/src/domain/zigbee-tools/green-power-sink.h @@ -85,7 +85,9 @@ class CGpSink : public CEzspDongleObserver CZigbeeMessaging &zb_messaging; CGpSinkTable sink_table; ESinkState sink_state; + // parameters to save for pairing CGpFrame gpf_comm_frame; + uint8_t sink_table_index; /** * Notify Observer of this class From a05fb155799e2061bcbf72f1399eca8404eb0198 Mon Sep 17 00:00:00 2001 From: seb Date: Fri, 15 Nov 2019 15:06:55 +0100 Subject: [PATCH 16/44] adding new class to simplify use of gp pairing ezsp command --- .../ember-process-gp-pairing-parameter.cpp | 7 ++ .../ember-process-gp-pairing-parameter.h | 77 +++++++++++++++++++ src/libezsp.mk.inc | 1 + 3 files changed, 85 insertions(+) create mode 100644 src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.cpp create mode 100644 src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h diff --git a/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.cpp b/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.cpp new file mode 100644 index 00000000..5b424dcb --- /dev/null +++ b/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.cpp @@ -0,0 +1,7 @@ +/** + * paramters for gpProxyTableProcessGpPairing (0xC9) command. + * reference is for docs-14-0563-16-batt-green-power-spec_ProxyBasic.pdf + */ + +#include "ember-process-gp-pairing-parameter.h" + diff --git a/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h b/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h new file mode 100644 index 00000000..082b1327 --- /dev/null +++ b/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h @@ -0,0 +1,77 @@ +/** + * paramters for gpProxyTableProcessGpPairing (0xC9) command. + * reference is for docs-14-0563-16-batt-green-power-spec_ProxyBasic.pdf + */ +#pragma once + +#include "../../byte-manip.h" +#include "../ezsp-enum.h" +#include "ember-gp-address-struct.h" + + +#ifdef USE_RARITAN +/**** Start of the official API; no includes below this point! ***************/ +#include +#endif // USE_RARITAN + +class CProcessGpPairingParam +{ + public: + /** + * @brief Default constructor + * + * Construction without arguments is not allowed + */ + CProcessGpPairingParam() = delete; + + /** + * @brief Copy constructor + * + * Copy construction is forbidden on this class + */ + CProcessGpPairingParam(const CProcessGpPairingParam& other) = delete; + + + private: + /** + * The options field of the GP Pairing command. + * see A.3.3.5.2 GP Pairing command for more details + */ + uint32_t options; + /** + * The target GPD. + */ + CEmberGpAddressStruct addr; + /** + * The communication mode of the GP Sink. + */ + uint8_t commMode; + /** + * The network address of the GP Sink. + */ + uint16_t sinkNetworkAddress; + /** + * The group ID of the GP Sink. + */ + uint16_t sinkGroupId; + /** + * The alias assigned to the GPD. + */ + uint16_t assignedAlias; + /** + * The IEEE address of the GP Sink. + */ + EmberEUI64 sinkIeeeAddress; + /** + * The key to use for the target GPD. + */ + EmberKeyData gpdKey; + /** + * The gpd security frame counter. + */ + uint32_t gpdSecurityFrameCounter; + /** + * The forwarding radius. + */ + uint8_t forwardingRadius; +}; \ No newline at end of file diff --git a/src/libezsp.mk.inc b/src/libezsp.mk.inc index 7b07a227..20c65ecc 100644 --- a/src/libezsp.mk.inc +++ b/src/libezsp.mk.inc @@ -19,6 +19,7 @@ LIBEZSP_COMMON_SRC = \ $(SRC_DOMAIN_PATH)/ezsp-protocol/struct/ember-gp-address-struct.cpp \ $(SRC_DOMAIN_PATH)/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp \ $(SRC_DOMAIN_PATH)/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp \ + $(SRC_DOMAIN_PATH)/ezsp-protocol/struct/ember-process-gp-pairing-parameter.cpp \ $(SRC_DOMAIN_PATH)/zigbee-tools/zigbee-networking.cpp \ $(SRC_DOMAIN_PATH)/zigbee-tools/zigbee-messaging.cpp \ $(SRC_DOMAIN_PATH)/zigbee-tools/green-power-sink.cpp \ From bd0cc9c49ef82337980e5777dadd984992afd27f Mon Sep 17 00:00:00 2001 From: seb Date: Fri, 15 Nov 2019 15:31:33 +0100 Subject: [PATCH 17/44] save sink table entry during commissioning process --- .../struct/ember-gp-address-struct.cpp | 10 ++ .../struct/ember-gp-address-struct.h | 4 +- .../ember-gp-sink-table-entry-struct.cpp | 64 ++++++++ .../struct/ember-gp-sink-table-entry-struct.h | 21 ++- .../ember-gp-sink-table-options-field.cpp | 16 ++ .../ember-gp-sink-table-options-field.h | 4 +- src/domain/zigbee-tools/green-power-sink.cpp | 148 ++++++++++-------- src/domain/zigbee-tools/green-power-sink.h | 1 + 8 files changed, 189 insertions(+), 79 deletions(-) diff --git a/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp b/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp index 51bed758..cf36ed4d 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp +++ b/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp @@ -8,6 +8,16 @@ #include "ember-gp-address-struct.h" +/** + * @brief Default constructor + */ +CEmberGpAddressStruct::CEmberGpAddressStruct(): + gpdIeeeAddress(), + applicationId(), + endpoint() +{ +} + /** * @brief Construction from itself * diff --git a/src/domain/ezsp-protocol/struct/ember-gp-address-struct.h b/src/domain/ezsp-protocol/struct/ember-gp-address-struct.h index 744108a4..c4c32bfb 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-address-struct.h +++ b/src/domain/ezsp-protocol/struct/ember-gp-address-struct.h @@ -13,10 +13,8 @@ class CEmberGpAddressStruct public: /** * @brief Default constructor - * - * Construction without arguments is not allowed */ - CEmberGpAddressStruct() = delete; + CEmberGpAddressStruct(); /** * @brief Construction from itself diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp index 74bb3a6a..bb857e66 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp @@ -11,6 +11,22 @@ #include "../../byte-manip.h" +CEmberGpSinkTableEntryStruct::CEmberGpSinkTableEntryStruct(): + status(0xFF), + options(), + gpd(), + device_id(), + sink_list(), + assigned_alias(), + groupcast_radius(), + security_options(), + gpdSecurity_frame_counter(), + gpd_key() +{ + sink_list[0].push_back(0xFF); + sink_list[1].push_back(0xFF); +} + CEmberGpSinkTableEntryStruct::CEmberGpSinkTableEntryStruct(const std::vector& raw_message): status(raw_message.at(0)), options(dble_u8_to_u16(raw_message.at(1),raw_message.at(2))), @@ -68,6 +84,54 @@ CEmberGpSinkTableEntryStruct::CEmberGpSinkTableEntryStruct(EmberGpSinkTableEntry sink_list[1].push_back(0xFF); } +/** + * @brief Copy constructor + */ +CEmberGpSinkTableEntryStruct::CEmberGpSinkTableEntryStruct(const CEmberGpSinkTableEntryStruct& other): + status(other.status), + options(other.options), + gpd(other.gpd), + device_id(other.device_id), + sink_list(other.sink_list), + assigned_alias(other.assigned_alias), + groupcast_radius(other.groupcast_radius), + security_options(other.security_options), + gpdSecurity_frame_counter(other.gpdSecurity_frame_counter), + gpd_key(other.gpd_key) +{ + +} + + +/** + * This method is a friend of CAPSFrame class + * swap() is needed within operator=() to implement to copy and swap paradigm +**/ +void swap(CEmberGpSinkTableEntryStruct& first, CEmberGpSinkTableEntryStruct& second) /* nothrow */ +{ + using std::swap; // Enable ADL + + swap(first.status, second.status); + swap(first.options, second.options); + swap(first.gpd, second.gpd); + swap(first.device_id, second.device_id); + swap(first.sink_list, second.sink_list); + swap(first.assigned_alias, second.assigned_alias); + swap(first.groupcast_radius, second.groupcast_radius); + swap(first.security_options, second.security_options); + swap(first.gpdSecurity_frame_counter, second.gpdSecurity_frame_counter); + swap(first.gpd_key, second.gpd_key); + /* Once we have swapped the members of the two instances... the two instances have actually been swapped */ +} + +/** + * @brief Assignment operator + */ +CEmberGpSinkTableEntryStruct& CEmberGpSinkTableEntryStruct::operator=(CEmberGpSinkTableEntryStruct other) +{ + swap(*this, other); + return *this; +} /** * @brief return structure as a raw diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h index 32990c3b..94ce7492 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h @@ -20,10 +20,8 @@ class CEmberGpSinkTableEntryStruct public: /** * @brief Default constructor - * - * Construction without arguments is not allowed */ - CEmberGpSinkTableEntryStruct() = delete; + CEmberGpSinkTableEntryStruct(); /** * @brief Construction from a buffer @@ -61,17 +59,24 @@ class CEmberGpSinkTableEntryStruct /** * @brief Copy constructor + */ + CEmberGpSinkTableEntryStruct(const CEmberGpSinkTableEntryStruct& other); + + /** + * @brief swap function to allow implementing of copy-and-swap idiom on members of type CEmberGpSinkTableOption + * + * This function will swap all attributes of \p first and \p second + * See http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom * - * Copy construction is forbidden on this class + * @param first The first object + * @param second The second object */ - CEmberGpSinkTableEntryStruct(const CEmberGpSinkTableEntryStruct& other) = delete; + friend void (::swap)(CEmberGpSinkTableEntryStruct& first, CEmberGpSinkTableEntryStruct& second); /** * @brief Assignment operator - * - * Assignment is forbidden on this class */ - CEmberGpSinkTableEntryStruct& operator=(const CEmberGpSinkTableEntryStruct& other) = delete; + CEmberGpSinkTableEntryStruct& operator=(CEmberGpSinkTableEntryStruct other); /** * @brief return structure as a raw diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp index 5f8220d9..8f2b6f2c 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp @@ -7,6 +7,22 @@ #include "ember-gp-sink-table-options-field.h" +/** + * @brief Default constructor + */ +CEmberGpSinkTableOption::CEmberGpSinkTableOption() : + application_id(), + communication_mode(), + sequence_number_capabilities(), + rx_on_capability(), + fixed_location(), + assigned_alias(), + security_use() +{ + +} + + /** * @brief Copy constructor */ diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h index b3a952d1..6943942f 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h @@ -27,10 +27,8 @@ class CEmberGpSinkTableOption public: /** * @brief Default constructor - * - * Construction without arguments is not allowed */ - CEmberGpSinkTableOption() = delete; + CEmberGpSinkTableOption(); /** * @brief Copy constructor diff --git a/src/domain/zigbee-tools/green-power-sink.cpp b/src/domain/zigbee-tools/green-power-sink.cpp index 7b3a030b..0f3ac4e7 100644 --- a/src/domain/zigbee-tools/green-power-sink.cpp +++ b/src/domain/zigbee-tools/green-power-sink.cpp @@ -67,6 +67,7 @@ CGpSink::CGpSink( CEzspDongle &i_dongle, CZigbeeMessaging &i_zb_messaging ) : sink_state(SINK_NOT_INIT), gpf_comm_frame(), sink_table_index(0xFF), + sink_table_entry(), observers() { dongle.registerObserver(this); @@ -259,6 +260,9 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re // call gpSinkSetEntry(sink_table_index,l_entry); + + // save + sink_table_entry = l_entry; } } break; @@ -267,71 +271,85 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re { if( SINK_COM_IN_PROGRESS == sink_state ) { - // do proxy pairing - std::vector l_struct; - uint32_t l_src_id = gpf_comm_frame.getSourceId(); - // The options field of the GP Pairing command - l_struct.push_back(0xA8); - l_struct.push_back(0xE5); - l_struct.push_back(0x02); - l_struct.push_back(0x00); - // The addressing info of the target GPD. - l_struct.push_back(0x00); // short address - l_struct.push_back(static_cast(l_src_id&0xFF)); - l_struct.push_back(static_cast((l_src_id>>8)&0xFF)); - l_struct.push_back(static_cast((l_src_id>>16)&0xFF)); - l_struct.push_back(static_cast((l_src_id>>24)&0xFF)); - l_struct.push_back(static_cast(l_src_id&0xFF)); - l_struct.push_back(static_cast((l_src_id>>8)&0xFF)); - l_struct.push_back(static_cast((l_src_id>>16)&0xFF)); - l_struct.push_back(static_cast((l_src_id>>24)&0xFF)); - l_struct.push_back(0x00); // endpoint -> not used - // The communication mode of the GP Sink. - l_struct.push_back(0x01); - // The network address of the GP Sink. - l_struct.push_back(0xFF); - l_struct.push_back(0xFF); - // The group ID of the GP Sink. - l_struct.push_back(l_src_id&0xFF); - l_struct.push_back((l_src_id>>8)&0xFF); - // The alias assigned to the GPD. - l_struct.push_back(0xFF); - l_struct.push_back(0xFF); - // The IEEE address of the GP Sink. - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - // The key to use for GPD. 59 13 29 50 28 9D 14 FD 73 F9 C3 25 D4 57 AB B5 - l_struct.push_back(0x59); - l_struct.push_back(0x13); - l_struct.push_back(0x29); - l_struct.push_back(0x50); - l_struct.push_back(0x28); - l_struct.push_back(0x9D); - l_struct.push_back(0x14); - l_struct.push_back(0xFD); - l_struct.push_back(0x73); - l_struct.push_back(0xF9); - l_struct.push_back(0xC3); - l_struct.push_back(0x25); - l_struct.push_back(0xD4); - l_struct.push_back(0x57); - l_struct.push_back(0xAB); - l_struct.push_back(0xB5); - // The security frame counter of the GPD. - l_struct.push_back(gpf_comm_frame.getPayload().at(23)); - l_struct.push_back(gpf_comm_frame.getPayload().at(24)); - l_struct.push_back(gpf_comm_frame.getPayload().at(25)); - l_struct.push_back(gpf_comm_frame.getPayload().at(26)); - // The forwarding radius. - l_struct.push_back(0x00); - // call - gpProxyTableProcessGpPairing(l_struct); + EEmberStatus l_status = static_cast(i_msg_receive.at(0)); + + // debug + clogD << "EZSP_GP_SINK_TABLE_SET_ENTRY Response status :" << CEzspEnum::EEmberStatusToString(l_status) << std::endl; + + if( EMBER_SUCCESS != l_status ) + { + // error + clogD << "ERROR, Stop commissioning process !!" << std::endl; + setSinkState(SINK_READY); + } + else + { + // do proxy pairing + std::vector l_struct; + uint32_t l_src_id = gpf_comm_frame.getSourceId(); + // The options field of the GP Pairing command + l_struct.push_back(0xA8); + l_struct.push_back(0xE5); + l_struct.push_back(0x02); + l_struct.push_back(0x00); + // The addressing info of the target GPD. + l_struct.push_back(0x00); // short address + l_struct.push_back(static_cast(l_src_id&0xFF)); + l_struct.push_back(static_cast((l_src_id>>8)&0xFF)); + l_struct.push_back(static_cast((l_src_id>>16)&0xFF)); + l_struct.push_back(static_cast((l_src_id>>24)&0xFF)); + l_struct.push_back(static_cast(l_src_id&0xFF)); + l_struct.push_back(static_cast((l_src_id>>8)&0xFF)); + l_struct.push_back(static_cast((l_src_id>>16)&0xFF)); + l_struct.push_back(static_cast((l_src_id>>24)&0xFF)); + l_struct.push_back(0x00); // endpoint -> not used + // The communication mode of the GP Sink. + l_struct.push_back(0x01); + // The network address of the GP Sink. + l_struct.push_back(0xFF); + l_struct.push_back(0xFF); + // The group ID of the GP Sink. + l_struct.push_back(l_src_id&0xFF); + l_struct.push_back((l_src_id>>8)&0xFF); + // The alias assigned to the GPD. + l_struct.push_back(0xFF); + l_struct.push_back(0xFF); + // The IEEE address of the GP Sink. + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + l_struct.push_back(0x00); + // The key to use for GPD. 59 13 29 50 28 9D 14 FD 73 F9 C3 25 D4 57 AB B5 + l_struct.push_back(0x59); + l_struct.push_back(0x13); + l_struct.push_back(0x29); + l_struct.push_back(0x50); + l_struct.push_back(0x28); + l_struct.push_back(0x9D); + l_struct.push_back(0x14); + l_struct.push_back(0xFD); + l_struct.push_back(0x73); + l_struct.push_back(0xF9); + l_struct.push_back(0xC3); + l_struct.push_back(0x25); + l_struct.push_back(0xD4); + l_struct.push_back(0x57); + l_struct.push_back(0xAB); + l_struct.push_back(0xB5); + // The security frame counter of the GPD. + l_struct.push_back(gpf_comm_frame.getPayload().at(23)); + l_struct.push_back(gpf_comm_frame.getPayload().at(24)); + l_struct.push_back(gpf_comm_frame.getPayload().at(25)); + l_struct.push_back(gpf_comm_frame.getPayload().at(26)); + // The forwarding radius. + l_struct.push_back(0x00); + // call + gpProxyTableProcessGpPairing(l_struct); + } } } break; diff --git a/src/domain/zigbee-tools/green-power-sink.h b/src/domain/zigbee-tools/green-power-sink.h index 627cfcd3..2eb56cff 100644 --- a/src/domain/zigbee-tools/green-power-sink.h +++ b/src/domain/zigbee-tools/green-power-sink.h @@ -88,6 +88,7 @@ class CGpSink : public CEzspDongleObserver // parameters to save for pairing CGpFrame gpf_comm_frame; uint8_t sink_table_index; + CEmberGpSinkTableEntryStruct sink_table_entry; /** * Notify Observer of this class From 7b332cd50af3b1957fb5040a7d11c69399b86669 Mon Sep 17 00:00:00 2001 From: Lionel AINS Date: Thu, 21 Nov 2019 12:20:27 +0100 Subject: [PATCH 18/44] Applying rename for method leaveNetwork() in class CZigbeeNetworking --- src/example/CAppDemo.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/example/CAppDemo.cpp b/src/example/CAppDemo.cpp index 3dd90146..55a643c8 100644 --- a/src/example/CAppDemo.cpp +++ b/src/example/CAppDemo.cpp @@ -401,7 +401,7 @@ void CAppDemo::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_r if(( APP_INIT_IN_PROGRESS == app_state ) && ( true == reset_wanted )) { // leave current network - zb_nwk.LeaveNetwork(); + zb_nwk.leaveNetwork(); setAppState(APP_LEAVE_IN_PROGRESS); reset_wanted = false; } From 9b1631b90312a6a597bb4b433111374d1f8874cd Mon Sep 17 00:00:00 2001 From: Lionel AINS Date: Thu, 21 Nov 2019 12:21:11 +0100 Subject: [PATCH 19/44] Opening GP commissionning session only if requested from the command-line --- src/example/CAppDemo.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/example/CAppDemo.cpp b/src/example/CAppDemo.cpp index 55a643c8..e24c555f 100644 --- a/src/example/CAppDemo.cpp +++ b/src/example/CAppDemo.cpp @@ -274,11 +274,12 @@ void CAppDemo::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_r { setAppState(APP_READY); - // init gp sink gp_sink.init(); - // for demo immediately open commissioning session - gp_sink.openCommissioningSession(); + if (this->openGpCommissionningAtStartup) { + // If requested to do so, immediately open a GP commissioning session + gp_sink.openCommissioningSession(); + } if (this->openZigbeeCommissionningAtStartup) { // If requested to do so, open the zigbee network for a specific duration, so new devices can join From bcd1574e3c09ed23678a4664ba869673c12b3144 Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 21 Nov 2019 12:45:02 +0100 Subject: [PATCH 20/44] adding new class to describe gp pairing command option --- .../gp-pairing-command-option-struct.cpp | 40 ++++++ .../gp-pairing-command-option-struct.h | 129 ++++++++++++++++++ src/libezsp.mk.inc | 1 + 3 files changed, 170 insertions(+) create mode 100644 src/domain/zbmessage/gp-pairing-command-option-struct.cpp create mode 100644 src/domain/zbmessage/gp-pairing-command-option-struct.h diff --git a/src/domain/zbmessage/gp-pairing-command-option-struct.cpp b/src/domain/zbmessage/gp-pairing-command-option-struct.cpp new file mode 100644 index 00000000..5ba1c664 --- /dev/null +++ b/src/domain/zbmessage/gp-pairing-command-option-struct.cpp @@ -0,0 +1,40 @@ +/** + * @file gp-pairing-command-option-struct.cpp + * + * @brief option field of gp pairing command according to A.3.3.5.2 GP Pairing command from docs-14-0563-16-batt-green-power-spec_ProxyBasic.pdf + */ + +#include "gp-pairing-command-option-struct.h" + +CGpPairingCommandOption::CGpPairingCommandOption(CEmberGpSinkTableOption i_sink_table_option, bool i_add_sink, bool i_remove_gpd, + uint8_t i_security_level, uint8_t i_security_key_type, bool i_frm_counter_present, + bool i_key_present, bool i_radius_present ): + application_id(i_sink_table_option.getApplicationId()), + add_sink(i_add_sink), + remove_gpd(i_remove_gpd), + communication_mode(i_sink_table_option.getCommunicationMode()), + gpd_fixed(i_sink_table_option.isFixedLocation()), + gpd_mac_seq_number_capability(i_sink_table_option.isSequenceNumberCapabilities()), + security_level(i_security_level), + security_key_type(i_security_key_type), + gpd_security_frame_counter_present(i_frm_counter_present), + gpd_security_key_present(i_key_present), + assigned_alias_present(i_sink_table_option.isAssignedAlias()), + forwarding_radius_present(i_radius_present) +{ + +} + +/** + * @brief option getter + */ +uint32_t CGpPairingCommandOption::get(void) +{ + uint32_t lo_option = 0; + + lo_option = (application_id<<0) | (add_sink<<3) | (remove_gpd<<4) | (communication_mode<<5) | (gpd_fixed<<7) | (gpd_mac_seq_number_capability<<8) | + (security_level<<9) | (security_key_type<<11) | (gpd_security_frame_counter_present<<14) | (gpd_security_key_present<<15) | + (assigned_alias_present<<16) | (forwarding_radius_present<<17) | 0; + + return lo_option; +} diff --git a/src/domain/zbmessage/gp-pairing-command-option-struct.h b/src/domain/zbmessage/gp-pairing-command-option-struct.h new file mode 100644 index 00000000..31e0b9c1 --- /dev/null +++ b/src/domain/zbmessage/gp-pairing-command-option-struct.h @@ -0,0 +1,129 @@ +/** + * @file gp-pairing-command-option-struct.h + * + * @brief option field of gp pairing command according to A.3.3.5.2 GP Pairing command from docs-14-0563-16-batt-green-power-spec_ProxyBasic.pdf + */ +#pragma once + +#include +#include + +#include "../ezsp-protocol/struct/ember-gp-sink-table-options-field.h" + +#ifdef USE_RARITAN +/**** Start of the official API; no includes below this point! ***************/ +#include +#endif // USE_RARITAN + +class CGpPairingCommandOption +{ + public: + /** + * @brief Default constructor + * + * Construction without arguments is not allowed + */ + CGpPairingCommandOption() = delete; + + /** + * @brief Copy constructor + * + * Copy construction is forbidden on this class + */ + CGpPairingCommandOption(const CGpPairingCommandOption& other) = delete; + + /** + * @brief constructor based on sink table entry option field + * + * @param i_sink_table_option + * @param i_add_sink : true to add, false to remove + * @param i_remove_gpd : true to remove + * @param i_security_level + * @param i_security_key_type + * @param i_frm_counter_present + * @param i_key_present + * @param i_radius_present + */ + CGpPairingCommandOption(CEmberGpSinkTableOption i_sink_table_option, bool i_add_sink, bool i_remove_gpd, + uint8_t i_security_level, uint8_t i_security_key_type, bool i_frm_counter_present, + bool i_key_present, bool i_radius_present ); + + /** + * @brief option getter + */ + uint32_t get(void); + + + private: + /** + * Bit 0..2: The ApplicationID sub-field contains t 3388 he information about the application used by the GPD. + * ApplicationID = 0b000 indicates the GPD ID field has the length of 4B and contains the GPD SrcID; the Endpoint field is absent. + * ApplicationID = 0b010 indicates the GPD ID field has the length of 8B and contains the GPD IEEE address; the Endpoint field is present. + * All values of ApplicationID other than 0b000 and 0b010 are reserved in the current version of the Green Power cluster specification. + */ + uint8_t application_id; + /** + * Bit 3: The AddSink sub-field of the Options field indicates, whether the GP sink wishes to add or remove a + * pairing for the GPD identified by the GPD ID. If set to 0b1 the pairing is being added. If set to 0b0 the + * pairing is being removed; then, the following fields are not present: DeviceID, GPD security Frame + * Counter, GPD key, AssignedAlias, and ForwardingRadius. + */ + bool add_sink; + /** + * Bit 4: The RemoveGPD sub-field of the Options field, if set to 0b1, indicates that the GPD identified by the + * GPD ID is being removed from the network. Then, none of the optional fields is present. + */ + bool remove_gpd; + /** + * Bit 5..6: The Communication mode sub-field defines the communication mode requested by the sink, and can take values as defined in Table 27. + */ + uint8_t communication_mode; + /** + * Bit 7: The GPDfixed sub-field and GPD MAC sequence number capabilities sub-field is copied from the corresponding + * FixedLocation and Sequence number capabilities sub-fields of the Options parameter of the Sink Table for this GPD. + */ + bool gpd_fixed; + /** + * Bit 8: see upper + */ + bool gpd_mac_seq_number_capability; + /** + * Bit 9..10: The SecurityLevel and SecurityKeyType SHALL carry the values of the corresponding parameters in Sink Table entry for this GPD. + */ + uint8_t security_level; + /** + * Bit 11..13: The sub-fields GPDsecurityFrameCounterPresent and GPDsecurityKeyPresent, if set to 0b1, indicate the presence of the fields + * GPDsecurityFrameCounter and GPDsecurityKey, respectively, which then carry the corresponding values from the Sink Table for this GPD. + * When the sub-fields GPDsecurityFrameCounterPresent and GPDsecurityKeyPresent are set to 0b0, + * the fields GPDsecurityFrame-Counter and GPDsecurityKey, respectively, are not present. + */ + uint8_t security_key_type; + /** + * Bit 14: The GPDsecurityFrameCounter field SHALL be present whenever the AddSink sub-field of the Options field is set to 0b1; + * independent of the security level. If the SecurityLevel sub-field is set to 0b10-0b11 or if the SecurityLevel is 0b00 and + * the GPD MAC sequence number capabilities sub-field is set to 0b1, the GPDsecurityFrameCounter field carries the current value of + * the GPD security frame counter field from the Sink Table entry corresponding to the GPD ID. If the SecurityLevel is 0b00 and + * the GPD MAC sequence number capabilities sub-field is set to 0b0, the GPDsecurityFrameCounter SHALL be set to 0b00000000. + */ + bool gpd_security_frame_counter_present; + /** + * Bit 15: see upper + */ + bool gpd_security_key_present; + /** + * Bit 16: The AssignedAlias present sub-field, if set to 0b1, indicates that the AssignedAlias field is present and + * carries the Alias value to be used for this GPD instead of the derived alias. + */ + bool assigned_alias_present; + /** + * Bit 17: The Forwarding Radius present sub-field, if set to 0b1, indicates that the Forwarding Radius field is + * present and carries the Forwarding Radius value to be used as value of the radius in the groupcast forwarding + * of the GPDF packet. If the Forwarding Radius field is not present, and a new Proxy Table entry is to be created, + * the default value of 0x00 SHALL be used. The value 0x00 indicates unspecified, + * i.e. twice the value of the nwkMaxDepth attribute of the NIB, as specified by [1]. + */ + bool forwarding_radius_present; + /** + * Bit 18..23: Reserved + */ +}; \ No newline at end of file diff --git a/src/libezsp.mk.inc b/src/libezsp.mk.inc index 20c65ecc..f82f9a09 100644 --- a/src/libezsp.mk.inc +++ b/src/libezsp.mk.inc @@ -5,6 +5,7 @@ LIBEZSP_COMMON_SRC = \ $(SRC_DOMAIN_PATH)/zbmessage/green-power-frame.cpp \ $(SRC_DOMAIN_PATH)/zbmessage/green-power-sink-table-entry.cpp \ $(SRC_DOMAIN_PATH)/zbmessage/gpd-commissioning-command-payload.cpp \ + $(SRC_DOMAIN_PATH)/zbmessage/gp-pairing-command-option-struct.cpp \ $(SRC_DOMAIN_PATH)/zbmessage/zigbee-message.cpp \ $(SRC_DOMAIN_PATH)/zbmessage/zclheader.cpp \ $(SRC_DOMAIN_PATH)/zbmessage/zclframecontrol.cpp \ From f91750d2e4ea1a8dba0df82ea5a9a993d510251d Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 21 Nov 2019 12:46:15 +0100 Subject: [PATCH 21/44] add define --- src/domain/ezsp-protocol/ezsp-enum.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/domain/ezsp-protocol/ezsp-enum.h b/src/domain/ezsp-protocol/ezsp-enum.h index e928dff1..dbe5fbb0 100644 --- a/src/domain/ezsp-protocol/ezsp-enum.h +++ b/src/domain/ezsp-protocol/ezsp-enum.h @@ -1064,6 +1064,9 @@ typedef uint8_t EmberGpSinkTableEntryStatus; #define EMBER_GP_SINK_LIST_ENTRY_SIZE 11 // why ? first byte to 0xFF is for not used ! typedef std::vector EmberGpSinkListEntry; +// assume this value is never reach for a frame counter +#define INVALID_FRAME_COUNTER 0xFFFFFFFF + #ifdef USE_RARITAN #include From f3f4bfd785353ba8efc63d13acff05c517838d3b Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 21 Nov 2019 12:46:40 +0100 Subject: [PATCH 22/44] add getters --- .../struct/ember-gp-sink-table-entry-struct.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h index 94ce7492..6d5b28c0 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h @@ -85,6 +85,19 @@ class CEmberGpSinkTableEntryStruct */ std::vector getRaw(void); + /** + * @brief getters + */ + CEmberGpSinkTableOption getOption(void){ return options; } + CEmberGpAddressStruct getGpdAddr(void){ return gpd; } + EmberNodeId getAssignedAlias(void){ return assigned_alias; } + EmberGpSecurityFrameCounter getSecurityFrameCounter(void){ return gpdSecurity_frame_counter; } + EmberKeyData getGpdKey(void){ return gpd_key; } + uint8_t getGroupcastRadius(void){ return groupcast_radius; } + uint8_t getSecurityLevel(void){ return security_options&0x03; } + uint8_t getSecurityKeyType(void){ return (security_options>>2)&0x07; } + bool isActive(void){ return status==0x01; } + /** * @brief status setter */ From bbe6c290d068ca88e13692effa548e885d90b9d2 Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 21 Nov 2019 12:47:37 +0100 Subject: [PATCH 23/44] fill class --- .../ember-process-gp-pairing-parameter.cpp | 60 +++++++++++++++++++ .../ember-process-gp-pairing-parameter.h | 22 ++++++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.cpp b/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.cpp index 5b424dcb..4462d8d2 100644 --- a/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.cpp +++ b/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.cpp @@ -5,3 +5,63 @@ #include "ember-process-gp-pairing-parameter.h" + + +CProcessGpPairingParam::CProcessGpPairingParam(CEmberGpSinkTableEntryStruct i_sink_table_entry, bool i_add_sink, bool i_remove_gpd, + uint16_t i_sinkNetworkAddress, EmberEUI64 i_sinkIeeeAddress ) : + options(i_sink_table_entry.getOption(), i_add_sink, i_remove_gpd, i_sink_table_entry.getSecurityLevel(), i_sink_table_entry.getSecurityKeyType(), true, true, true), + addr(i_sink_table_entry.getGpdAddr()), + commMode(i_sink_table_entry.getOption().getCommunicationMode()), + sinkNetworkAddress(i_sinkNetworkAddress), + sinkGroupId(static_cast(i_sink_table_entry.getGpdAddr().getSourceId()&0xFFFF)), + assignedAlias(i_sink_table_entry.getAssignedAlias()), + sinkIeeeAddress(i_sinkIeeeAddress), + gpdKey(i_sink_table_entry.getGpdKey()), + gpdSecurityFrameCounter(i_sink_table_entry.getSecurityFrameCounter()), + forwardingRadius(i_sink_table_entry.getGroupcastRadius()) +{ + +} + + +/** + * @brief raw getter + */ +std::vector CProcessGpPairingParam::get(void) +{ + std::vector lo_out; + + // The options field of the GP Pairing command + uint32_t l_option = options.get(); + lo_out.push_back(static_cast(l_option&0xFF)); + lo_out.push_back(static_cast((l_option>>8)&0xFF)); + lo_out.push_back(static_cast((l_option>>16)&0xFF)); + lo_out.push_back(static_cast((l_option>>24)&0xFF)); + // The addressing info of the target GPD. + std::vector l_gpd_addr = addr.getRaw(); + lo_out.insert(lo_out.end(),l_gpd_addr.begin(),l_gpd_addr.end()); + // The communication mode of the GP Sink. + lo_out.push_back(commMode); + // The network address of the GP Sink. + lo_out.push_back(static_cast(sinkNetworkAddress&0xFF)); + lo_out.push_back(static_cast((sinkNetworkAddress>>8)&0xFF)); + // The group ID of the GP Sink. + lo_out.push_back(static_cast(sinkGroupId&0xFF)); + lo_out.push_back(static_cast((sinkGroupId>>8)&0xFF)); + // The alias assigned to the GPD. + lo_out.push_back(static_cast(assignedAlias&0xFF)); + lo_out.push_back(static_cast((assignedAlias>>8)&0xFF)); + // The IEEE address of the GP Sink. + lo_out.insert(lo_out.end(),sinkIeeeAddress.begin(),sinkIeeeAddress.end()); + // The key to use for GPD. + lo_out.insert(lo_out.end(),gpdKey.begin(),gpdKey.end()); + // The security frame counter of the GPD. + lo_out.push_back(static_cast(gpdSecurityFrameCounter&0xFF)); + lo_out.push_back(static_cast((gpdSecurityFrameCounter>>8)&0xFF)); + lo_out.push_back(static_cast((gpdSecurityFrameCounter>>16)&0xFF)); + lo_out.push_back(static_cast((gpdSecurityFrameCounter>>24)&0xFF)); + // The forwarding radius. + lo_out.push_back(forwardingRadius); + + return lo_out; +} diff --git a/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h b/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h index 082b1327..295e4372 100644 --- a/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h +++ b/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h @@ -7,6 +7,8 @@ #include "../../byte-manip.h" #include "../ezsp-enum.h" #include "ember-gp-address-struct.h" +#include "ember-gp-sink-table-entry-struct.h" +#include "../../zbmessage/gp-pairing-command-option-struct.h" #ifdef USE_RARITAN @@ -31,13 +33,31 @@ class CProcessGpPairingParam */ CProcessGpPairingParam(const CProcessGpPairingParam& other) = delete; + /** + * @brief constructor using sink table entry and extra parameter + * + * @param i_sink_table_entry : sink table entry corresponding to gpd + * @param i_add_sink : true to add, false to remove + * @param i_remove_gpd : true to remove + * @param i_sinkNetworkAddress : short network address of sink + * @param i_sinkIeeeAddress : long network address of sink + */ + CProcessGpPairingParam(CEmberGpSinkTableEntryStruct i_sink_table_entry, bool i_add_sink, bool i_remove_gpd, + uint16_t i_sinkNetworkAddress, EmberEUI64 i_sinkIeeeAddress ); + + + /** + * @brief raw getter + */ + std::vector get(void); + private: /** * The options field of the GP Pairing command. * see A.3.3.5.2 GP Pairing command for more details */ - uint32_t options; + CGpPairingCommandOption options; /** * The target GPD. */ From 9f3875d33eb3188b3ef5a6cd54175da57ad561bb Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 21 Nov 2019 12:47:58 +0100 Subject: [PATCH 24/44] use new class in place of vector --- src/domain/zigbee-tools/green-power-sink.cpp | 75 ++------------------ src/domain/zigbee-tools/green-power-sink.h | 3 +- 2 files changed, 7 insertions(+), 71 deletions(-) diff --git a/src/domain/zigbee-tools/green-power-sink.cpp b/src/domain/zigbee-tools/green-power-sink.cpp index 0f3ac4e7..3434a070 100644 --- a/src/domain/zigbee-tools/green-power-sink.cpp +++ b/src/domain/zigbee-tools/green-power-sink.cpp @@ -285,70 +285,10 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re else { // do proxy pairing - std::vector l_struct; - uint32_t l_src_id = gpf_comm_frame.getSourceId(); - // The options field of the GP Pairing command - l_struct.push_back(0xA8); - l_struct.push_back(0xE5); - l_struct.push_back(0x02); - l_struct.push_back(0x00); - // The addressing info of the target GPD. - l_struct.push_back(0x00); // short address - l_struct.push_back(static_cast(l_src_id&0xFF)); - l_struct.push_back(static_cast((l_src_id>>8)&0xFF)); - l_struct.push_back(static_cast((l_src_id>>16)&0xFF)); - l_struct.push_back(static_cast((l_src_id>>24)&0xFF)); - l_struct.push_back(static_cast(l_src_id&0xFF)); - l_struct.push_back(static_cast((l_src_id>>8)&0xFF)); - l_struct.push_back(static_cast((l_src_id>>16)&0xFF)); - l_struct.push_back(static_cast((l_src_id>>24)&0xFF)); - l_struct.push_back(0x00); // endpoint -> not used - // The communication mode of the GP Sink. - l_struct.push_back(0x01); - // The network address of the GP Sink. - l_struct.push_back(0xFF); - l_struct.push_back(0xFF); - // The group ID of the GP Sink. - l_struct.push_back(l_src_id&0xFF); - l_struct.push_back((l_src_id>>8)&0xFF); - // The alias assigned to the GPD. - l_struct.push_back(0xFF); - l_struct.push_back(0xFF); - // The IEEE address of the GP Sink. - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - l_struct.push_back(0x00); - // The key to use for GPD. 59 13 29 50 28 9D 14 FD 73 F9 C3 25 D4 57 AB B5 - l_struct.push_back(0x59); - l_struct.push_back(0x13); - l_struct.push_back(0x29); - l_struct.push_back(0x50); - l_struct.push_back(0x28); - l_struct.push_back(0x9D); - l_struct.push_back(0x14); - l_struct.push_back(0xFD); - l_struct.push_back(0x73); - l_struct.push_back(0xF9); - l_struct.push_back(0xC3); - l_struct.push_back(0x25); - l_struct.push_back(0xD4); - l_struct.push_back(0x57); - l_struct.push_back(0xAB); - l_struct.push_back(0xB5); - // The security frame counter of the GPD. - l_struct.push_back(gpf_comm_frame.getPayload().at(23)); - l_struct.push_back(gpf_comm_frame.getPayload().at(24)); - l_struct.push_back(gpf_comm_frame.getPayload().at(25)); - l_struct.push_back(gpf_comm_frame.getPayload().at(26)); - // The forwarding radius. - l_struct.push_back(0x00); + // \todo replace short and long sink network address by right value, currently we use group mode not so important + CProcessGpPairingParam l_param( sink_table_entry, true, false, 0, {0,0,0,0,0,0,0,0} ); // call - gpProxyTableProcessGpPairing(l_struct); + gpProxyTableProcessGpPairing(l_param); } } } @@ -613,15 +553,10 @@ void CGpSink::gpSinkSetEntry( uint8_t i_index, CEmberGpSinkTableEntryStruct& i_e /** * Update the GP Proxy table based on a GP pairing. */ -void CGpSink::gpProxyTableProcessGpPairing( std::vector i_param ) +void CGpSink::gpProxyTableProcessGpPairing( CProcessGpPairingParam& i_param ) { - std::vector l_payload; - - // \todo used seperate paramter or a dedicated struct class - l_payload.insert(l_payload.end(), i_param.begin(), i_param.end()); - clogI << "EZSP_GP_PROXY_TABLE_PROCESS_GP_PAIRING\n"; - dongle.sendCommand(EZSP_GP_PROXY_TABLE_PROCESS_GP_PAIRING,l_payload); + dongle.sendCommand(EZSP_GP_PROXY_TABLE_PROCESS_GP_PAIRING,i_param.get()); } diff --git a/src/domain/zigbee-tools/green-power-sink.h b/src/domain/zigbee-tools/green-power-sink.h index 2eb56cff..48ce670c 100644 --- a/src/domain/zigbee-tools/green-power-sink.h +++ b/src/domain/zigbee-tools/green-power-sink.h @@ -10,6 +10,7 @@ #include "zigbee-messaging.h" #include "green-power-sink-table.h" #include "../ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h" +#include "../ezsp-protocol/struct/ember-process-gp-pairing-parameter.h" #ifdef USE_RARITAN /**** Start of the official API; no includes below this point! ***************/ @@ -128,7 +129,7 @@ class CGpSink : public CEzspDongleObserver /** * Update the GP Proxy table based on a GP pairing. */ - void gpProxyTableProcessGpPairing( std::vector i_param ); + void gpProxyTableProcessGpPairing( CProcessGpPairingParam& i_param ); }; #ifdef USE_RARITAN From 9d5f9684c5a7ff6904a4e41a69178d8e69355ba4 Mon Sep 17 00:00:00 2001 From: Lionel AINS Date: Thu, 21 Nov 2019 14:40:55 +0100 Subject: [PATCH 25/44] Rework on doxygen comments and adding const qualifier whenever needed --- .../struct/ember-gp-address-struct.cpp | 23 ++--- .../struct/ember-gp-address-struct.h | 20 ++-- .../ember-gp-sink-table-entry-struct.cpp | 40 +------- .../struct/ember-gp-sink-table-entry-struct.h | 61 ++++++------ .../ember-gp-sink-table-options-field.cpp | 26 +++-- .../ember-gp-sink-table-options-field.h | 98 ++++++++++++------- .../ember-process-gp-pairing-parameter.cpp | 12 +-- .../ember-process-gp-pairing-parameter.h | 64 ++++-------- .../gp-pairing-command-option-struct.cpp | 5 +- .../gp-pairing-command-option-struct.h | 38 +++---- .../gpd-commissioning-command-payload.cpp | 9 +- .../gpd-commissioning-command-payload.h | 66 ++++++------- src/domain/zbmessage/green-power-frame.h | 27 +++-- src/domain/zbmessage/zigbee-message.cpp | 41 -------- src/domain/zbmessage/zigbee-message.h | 54 +++++----- src/domain/zigbee-tools/green-power-sink.cpp | 35 ++----- src/domain/zigbee-tools/green-power-sink.h | 36 ++++--- src/example/mainEzspTest.cpp | 2 +- 18 files changed, 280 insertions(+), 377 deletions(-) diff --git a/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp b/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp index cf36ed4d..b0588db8 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp +++ b/src/domain/ezsp-protocol/struct/ember-gp-address-struct.cpp @@ -8,9 +8,6 @@ #include "ember-gp-address-struct.h" -/** - * @brief Default constructor - */ CEmberGpAddressStruct::CEmberGpAddressStruct(): gpdIeeeAddress(), applicationId(), @@ -18,15 +15,10 @@ CEmberGpAddressStruct::CEmberGpAddressStruct(): { } -/** - * @brief Construction from itself - * - * @param i_gpd_address gpd address from construct - */ -CEmberGpAddressStruct::CEmberGpAddressStruct(const CEmberGpAddressStruct& i_gpd_address): - gpdIeeeAddress(i_gpd_address.getGpdIeeeAddress()), - applicationId(i_gpd_address.getApplicationId()), - endpoint(i_gpd_address.getEndpoint()) +CEmberGpAddressStruct::CEmberGpAddressStruct(const CEmberGpAddressStruct& other): + gpdIeeeAddress(other.getGpdIeeeAddress()), + applicationId(other.getApplicationId()), + endpoint(other.getEndpoint()) { } @@ -38,7 +30,7 @@ CEmberGpAddressStruct::CEmberGpAddressStruct(const std::vector& raw_mes } /** - * This method is a friend of CAPSFrame class + * This method is a friend of CEmberGpAddressStruct class * swap() is needed within operator=() to implement to copy and swap paradigm **/ void swap(CEmberGpAddressStruct& first, CEmberGpAddressStruct& second) /* nothrow */ @@ -51,9 +43,6 @@ void swap(CEmberGpAddressStruct& first, CEmberGpAddressStruct& second) /* nothro /* Once we have swapped the members of the two instances... the two instances have actually been swapped */ } -/** - * @brief Assignment operator - */ CEmberGpAddressStruct& CEmberGpAddressStruct::operator=(CEmberGpAddressStruct other) { swap(*this, other); @@ -77,7 +66,7 @@ CEmberGpAddressStruct::CEmberGpAddressStruct(const uint32_t i_srcId): gpdIeeeAddress.push_back(static_cast((i_srcId>>24)&0xFF)); } -std::vector CEmberGpAddressStruct::getRaw(void) +std::vector CEmberGpAddressStruct::getRaw() const { std::vector lo_raw; diff --git a/src/domain/ezsp-protocol/struct/ember-gp-address-struct.h b/src/domain/ezsp-protocol/struct/ember-gp-address-struct.h index c4c32bfb..c40a84a2 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-address-struct.h +++ b/src/domain/ezsp-protocol/struct/ember-gp-address-struct.h @@ -17,11 +17,11 @@ class CEmberGpAddressStruct CEmberGpAddressStruct(); /** - * @brief Construction from itself + * @brief Copy constructor * - * @param i_gpd_address gpd address from construct + * @param other The object instance to construct from */ - CEmberGpAddressStruct(const CEmberGpAddressStruct& i_gpd_address); + CEmberGpAddressStruct(const CEmberGpAddressStruct& other); /** * @brief Construction from a buffer @@ -38,7 +38,7 @@ class CEmberGpAddressStruct CEmberGpAddressStruct(const uint32_t i_srcId); /** - * @brief swap function to allow implementing of copy-and-swap idiom on members of type CEmberGpSinkTableOption + * @brief swap function to allow implementing of copy-and-swap idiom on members of type CEmberGpAddressStruct * * This function will swap all attributes of \p first and \p second * See http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom @@ -50,6 +50,9 @@ class CEmberGpAddressStruct /** * @brief Assignment operator + * @param other The object to assign to the lhs + * + * @return The object that has been assigned the value of @p other */ CEmberGpAddressStruct& operator=(CEmberGpAddressStruct other); @@ -78,7 +81,7 @@ class CEmberGpAddressStruct * * @return raw buffer */ - std::vector getRaw(void); + std::vector getRaw() const; /** * @brief Dump this instance as a string @@ -98,9 +101,8 @@ class CEmberGpAddressStruct friend std::ostream& operator<< (std::ostream& out, const CEmberGpAddressStruct& data); private: - - EmberEUI64 gpdIeeeAddress; // The GPD's EUI64. - uint8_t applicationId; // The GPD Application ID. - uint8_t endpoint; // The GPD endpoint. + EmberEUI64 gpdIeeeAddress; /*!< The GPD's EUI64 */ + uint8_t applicationId; /*!< The GPD Application ID */ + uint8_t endpoint; /*!< The GPD endpoint */ }; diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp index bb857e66..05145ea2 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp @@ -1,7 +1,7 @@ /** * @file ember-g-sink-table-entry-struct.cpp * - * @brief The internal representation of a sink table entry. + * @brief Represents one sink table entry from Ember */ #include @@ -43,29 +43,6 @@ CEmberGpSinkTableEntryStruct::CEmberGpSinkTableEntryStruct(const std::vector CEmberGpSinkTableEntryStruct::getRaw(void) +std::vector CEmberGpSinkTableEntryStruct::getRaw() const { std::vector l_struct; diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h index 6d5b28c0..c4cb75d7 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h @@ -1,7 +1,7 @@ /** * @file ember-gp-sink-table-entry-struct.h * - * @brief The internal representation of a sink table entry. + * @brief Represents one sink table entry from Ember */ #pragma once @@ -59,11 +59,13 @@ class CEmberGpSinkTableEntryStruct /** * @brief Copy constructor + * + * @param other The object instance to construct from */ CEmberGpSinkTableEntryStruct(const CEmberGpSinkTableEntryStruct& other); /** - * @brief swap function to allow implementing of copy-and-swap idiom on members of type CEmberGpSinkTableOption + * @brief swap function to allow implementing of copy-and-swap idiom on members of type CEmberGpSinkTableEntryStruct * * This function will swap all attributes of \p first and \p second * See http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom @@ -75,6 +77,9 @@ class CEmberGpSinkTableEntryStruct /** * @brief Assignment operator + * @param other The object to assign to the lhs + * + * @return The object that has been assigned the value of @p other */ CEmberGpSinkTableEntryStruct& operator=(CEmberGpSinkTableEntryStruct other); @@ -83,25 +88,25 @@ class CEmberGpSinkTableEntryStruct * * @return raw of structure */ - std::vector getRaw(void); + std::vector getRaw() const; /** * @brief getters */ - CEmberGpSinkTableOption getOption(void){ return options; } - CEmberGpAddressStruct getGpdAddr(void){ return gpd; } - EmberNodeId getAssignedAlias(void){ return assigned_alias; } - EmberGpSecurityFrameCounter getSecurityFrameCounter(void){ return gpdSecurity_frame_counter; } - EmberKeyData getGpdKey(void){ return gpd_key; } - uint8_t getGroupcastRadius(void){ return groupcast_radius; } - uint8_t getSecurityLevel(void){ return security_options&0x03; } - uint8_t getSecurityKeyType(void){ return (security_options>>2)&0x07; } - bool isActive(void){ return status==0x01; } + CEmberGpSinkTableOption getOption() const { return options; } + CEmberGpAddressStruct getGpdAddr() const { return gpd; } + EmberNodeId getAssignedAlias() const { return assigned_alias; } + EmberGpSecurityFrameCounter getSecurityFrameCounter() const { return gpdSecurity_frame_counter; } + EmberKeyData getGpdKey() const { return gpd_key; } + uint8_t getGroupcastRadius() const { return groupcast_radius; } + uint8_t getSecurityLevel() const { return security_options&0x03; } + uint8_t getSecurityKeyType() const { return (security_options>>2)&0x07; } + bool isActive() const { return status==0x01; } /** * @brief status setter */ - void setEntryActive(bool i_active){ i_active?status=0x01:status=0xFF; } + void setEntryActive(bool i_active) { this->status=(i_active?0x01:0xFF); } /** * @brief options setter @@ -156,26 +161,16 @@ class CEmberGpSinkTableEntryStruct friend std::ostream& operator<< (std::ostream& out, const CEmberGpSinkTableEntryStruct& data); private: - // Internal status of the sink table entry. - EmberGpSinkTableEntryStatus status; - // The tunneling options (this contains both options and extendedOptions from the spec). WRONG Specification only 16 bits like option without extended ... - CEmberGpSinkTableOption options; - // The addressing info of the GPD. - CEmberGpAddressStruct gpd; - // The device id for the GPD. - uint8_t device_id; - // The list of sinks (hardcoded to 2 which is the spec minimum). - EmberGpSinkListEntry sink_list[GP_SINK_LIST_ENTRIES]; - // The assigned alias for the GPD. - EmberNodeId assigned_alias; - // The groupcast radius. - uint8_t groupcast_radius; - // The security options field. - uint8_t security_options; - // The security frame counter of the GPD. - EmberGpSecurityFrameCounter gpdSecurity_frame_counter; - // The key to use for GPD. - EmberKeyData gpd_key; + EmberGpSinkTableEntryStatus status; /*!< Internal status of the sink table entry */ + CEmberGpSinkTableOption options; /*!< The tunneling options (this contains both options and extendedOptions from the spec). WRONG Specification only 16 bits like option without extended... */ + CEmberGpAddressStruct gpd; /*!< The addressing info of the GPD */ + uint8_t device_id; /*!< The device id for the GPD */ + EmberGpSinkListEntry sink_list[GP_SINK_LIST_ENTRIES]; /*!< The list of sinks (hardcoded to 2 which is the spec minimum) */ + EmberNodeId assigned_alias; /*!< The assigned alias for the GPD */ + uint8_t groupcast_radius; /*!< The groupcast radius */ + uint8_t security_options; /*!< The security options field */ + EmberGpSecurityFrameCounter gpdSecurity_frame_counter; /*!< The security frame counter of the GPD */ + EmberKeyData gpd_key; /*!< The key to use for GPD */ }; #ifdef USE_RARITAN diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp index 8f2b6f2c..13d51954 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp @@ -1,15 +1,24 @@ /** -* @brief Details of options bit filed for sink table entry -*/ + * @file ember-gp-sink-table-option-field.cpp + * + * @brief Represents Ember's sink table entry options bit field + * + * option : 0x02A8 (cf. A3.3.2.2.1 Options parameter of the Sink Table from doc doc-14-0563-16-batt-green-power-spec_ProxyBasic.pdf) + * - bits 0..2 : Application Id (0b000 : use source Id) + * - bits 3..4 : Communication mode (0b01 : groupcast forwarding of the GP Notification command to DGroupID) + * - bit 5 : Sequence number capabilities (0b1 : use incremental sequence number) + * - bit 6 : RxOnCapability (0b0 : not capable) + * - bit 7 : FixedLocation (0b1 : not a mobile device) + * - bit 8 : AssignedAlias (0b0 : the derived alias is used) + * - bit 9 : Security use (0b1 : indicates that security-related parameters of the Sink Table entry are present) + * - bit 10..15 : Reserved + */ #include #include #include "ember-gp-sink-table-options-field.h" -/** - * @brief Default constructor - */ CEmberGpSinkTableOption::CEmberGpSinkTableOption() : application_id(), communication_mode(), @@ -23,9 +32,6 @@ CEmberGpSinkTableOption::CEmberGpSinkTableOption() : } -/** - * @brief Copy constructor - */ CEmberGpSinkTableOption::CEmberGpSinkTableOption(const CEmberGpSinkTableOption& other) : application_id(other.application_id), communication_mode(other.communication_mode), @@ -80,7 +86,7 @@ CEmberGpSinkTableOption::CEmberGpSinkTableOption(const uint8_t i_application_id, } /** - * This method is a friend of CAPSFrame class + * This method is a friend of CEmberGpSinkTableOption class * swap() is needed within operator=() to implement to copy and swap paradigm **/ void swap(CEmberGpSinkTableOption& first, CEmberGpSinkTableOption& second) /* nothrow */ @@ -106,7 +112,7 @@ CEmberGpSinkTableOption& CEmberGpSinkTableOption::operator=( CEmberGpSinkTableOp /** * raw getter */ -uint16_t CEmberGpSinkTableOption::get(void) +uint16_t CEmberGpSinkTableOption::get() const { uint16_t o_options = 0 + \ application_id + \ diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h index 6943942f..cf64af30 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h @@ -1,15 +1,18 @@ /** -* @brief Details of options bit filed for sink table entry -* option : 0x02A8 (cf. A3.3.2.2.1 Options parameter of the Sink Table from doc doc-14-0563-16-batt-green-power-spec_ProxyBasic.pdf) -* - bits 0..2 : Application Id (0b000 : use source Id) -* - bits 3..4 : Communication mode (0b01 : groupcast forwarding of the GP Notification command to DGroupID) -* - bit 5 : Sequence number capabilities (0b1 : use incremental sequence number) -* - bit 6 : RxOnCapability (0b0 : not capable) -* - bit 7 : FixedLocation (0b1 : not a mobile device) -* - bit 8 : AssignedAlias (0b0 : the derived alias is used) -* - bit 9 : Security use (0b1 : indicates that security-related parameters of the Sink Table entry are present) -* - bit 10..15 : Reserved -*/ + * @file ember-gp-sink-table-option-field.h + * + * @brief Represents Ember's sink table entry options bit field + * + * option : 0x02A8 (cf. A3.3.2.2.1 Options parameter of the Sink Table from doc doc-14-0563-16-batt-green-power-spec_ProxyBasic.pdf) + * - bits 0..2 : Application Id (0b000 : use source Id) + * - bits 3..4 : Communication mode (0b01 : groupcast forwarding of the GP Notification command to DGroupID) + * - bit 5 : Sequence number capabilities (0b1 : use incremental sequence number) + * - bit 6 : RxOnCapability (0b0 : not capable) + * - bit 7 : FixedLocation (0b1 : not a mobile device) + * - bit 8 : AssignedAlias (0b0 : the derived alias is used) + * - bit 9 : Security use (0b1 : indicates that security-related parameters of the Sink Table entry are present) + * - bit 10..15 : Reserved + */ #pragma once @@ -32,11 +35,15 @@ class CEmberGpSinkTableOption /** * @brief Copy constructor + * + * @param other The object to copy from */ CEmberGpSinkTableOption(const CEmberGpSinkTableOption& other); /** * @brief Assignment operator + * + * @param other The object to assign from */ CEmberGpSinkTableOption& operator=( CEmberGpSinkTableOption other); @@ -65,39 +72,60 @@ class CEmberGpSinkTableOption CEmberGpSinkTableOption(const uint8_t i_application_id, CGpdCommissioningPayload i_gpdf_commissioning_payload); /** - * @brief raw getter + * @brief Raw getter + * + * @return This option field object represented as a 16-bit word */ - uint16_t get(void); + uint16_t get() const; /** - * @brief application_id getter + * @brief Getter for the enclosed application ID + * + * @return The enclosed application ID */ - uint8_t getApplicationId(void){ return application_id; } + uint8_t getApplicationId() const { return application_id; } + /** - * @brief communication_mode getter + * @brief Getter for the enclosed communication mode + * + * @return The enclosed communication mode */ - uint8_t getCommunicationMode(void){ return communication_mode; } + uint8_t getCommunicationMode() const { return communication_mode; } + /** - * @brief sequence_number_capabilities getter + * @brief Getter for the enclosed sequence number capabilities + * + * @return The enclosed sequence number capabilities */ - bool isSequenceNumberCapabilities(void){ return sequence_number_capabilities; } + bool isSequenceNumberCapabilities() const { return sequence_number_capabilities; } + /** - * @brief rx_on_capability getter + * @brief Getter for the enclosed RX On capability + * + * @return true if this object contains an RX On capability */ - bool isRxOnCapability(void){ return rx_on_capability; } + bool isRxOnCapability() const { return rx_on_capability; } + /** - * @brief fixed_location getter + * @brief Getter for the enclosed fixed location + * + * @return true if this object contains a fixed location capability */ - bool isFixedLocation(void){ return fixed_location; } + bool isFixedLocation() const { return fixed_location; } + /** - * @brief assigned_alias getter + * @brief Getter for the enclosed assigned alias + * + * @return true if this object contains an assigned alias */ - bool isAssignedAlias(void){ return assigned_alias; } + bool isAssignedAlias() const { return assigned_alias; } + /** - * @brief security_use getter + * @brief Getter for the enclosed security use + * + * @return true if this object uses security */ - bool isSecurityUse(void){ return security_use; } - + bool isSecurityUse() const { return security_use; } /** * @brief Dump this instance as a string @@ -117,11 +145,11 @@ class CEmberGpSinkTableOption friend std::ostream& operator<< (std::ostream& out, const CEmberGpSinkTableOption& data); private: - uint8_t application_id; - uint8_t communication_mode; - bool sequence_number_capabilities; - bool rx_on_capability; - bool fixed_location; - bool assigned_alias; - bool security_use; + uint8_t application_id; /*!< The application ID contained in this sink table entry options bit field */ + uint8_t communication_mode; /*!< The communication mode contained in this sink table entry options bit field */ + bool sequence_number_capabilities; /*!< The sequence number capabilities contained in this sink table entry options bit field */ + bool rx_on_capability; /*!< The RX On capavility toggle contained in this sink table entry options bit field */ + bool fixed_location; /*!< The fixed location toggle contained in this sink table entry options bit field */ + bool assigned_alias; /*!< The assigned alias toggle contained in this sink table entry options bit field */ + bool security_use; /*!< The security use toggle contained in this sink table entry options bit field */ }; \ No newline at end of file diff --git a/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.cpp b/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.cpp index 4462d8d2..e611435d 100644 --- a/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.cpp +++ b/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.cpp @@ -1,6 +1,9 @@ /** - * paramters for gpProxyTableProcessGpPairing (0xC9) command. - * reference is for docs-14-0563-16-batt-green-power-spec_ProxyBasic.pdf + * @file ember-process-gp-pairing-parameter.cpp + * + * @brief Parameters for gpProxyTableProcessGpPairing (0xC9) command. + * + * Reference: docs-14-0563-16-batt-green-power-spec_ProxyBasic.pdf */ #include "ember-process-gp-pairing-parameter.h" @@ -24,10 +27,7 @@ CProcessGpPairingParam::CProcessGpPairingParam(CEmberGpSinkTableEntryStruct i_si } -/** - * @brief raw getter - */ -std::vector CProcessGpPairingParam::get(void) +std::vector CProcessGpPairingParam::get() const { std::vector lo_out; diff --git a/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h b/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h index 295e4372..fad82133 100644 --- a/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h +++ b/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h @@ -1,6 +1,9 @@ /** - * paramters for gpProxyTableProcessGpPairing (0xC9) command. - * reference is for docs-14-0563-16-batt-green-power-spec_ProxyBasic.pdf + * @file ember-process-gp-pairing-parameter.h + * + * @brief Parameters for gpProxyTableProcessGpPairing (0xC9) command. + * + * Reference: docs-14-0563-16-batt-green-power-spec_ProxyBasic.pdf */ #pragma once @@ -47,51 +50,22 @@ class CProcessGpPairingParam /** - * @brief raw getter + * @brief Raw getter + * + * @return This object represented as a raw byte-buffer */ - std::vector get(void); + std::vector get() const; private: - /** - * The options field of the GP Pairing command. - * see A.3.3.5.2 GP Pairing command for more details - */ - CGpPairingCommandOption options; - /** - * The target GPD. - */ - CEmberGpAddressStruct addr; - /** - * The communication mode of the GP Sink. - */ - uint8_t commMode; - /** - * The network address of the GP Sink. - */ - uint16_t sinkNetworkAddress; - /** - * The group ID of the GP Sink. - */ - uint16_t sinkGroupId; - /** - * The alias assigned to the GPD. - */ - uint16_t assignedAlias; - /** - * The IEEE address of the GP Sink. - */ - EmberEUI64 sinkIeeeAddress; - /** - * The key to use for the target GPD. - */ - EmberKeyData gpdKey; - /** - * The gpd security frame counter. - */ - uint32_t gpdSecurityFrameCounter; - /** - * The forwarding radius. - */ - uint8_t forwardingRadius; + CGpPairingCommandOption options; /*!< The options field of the GP Pairing command (see A.3.3.5.2 GP Pairing command for more details) */ + CEmberGpAddressStruct addr; /*!< The target GPD */ + uint8_t commMode; /*!< The communication mode of the GP Sink */ + uint16_t sinkNetworkAddress; /*!< The network address of the GP Sink */ + uint16_t sinkGroupId; /*!< The group ID of the GP Sink */ + uint16_t assignedAlias; /*!< The alias assigned to the GPD */ + EmberEUI64 sinkIeeeAddress; /*!< The IEEE address of the GP Sink */ + EmberKeyData gpdKey; /*!< The key to use for the target GPD */ + uint32_t gpdSecurityFrameCounter; /*!< The gpd security frame counter */ + uint8_t forwardingRadius; /*!< The forwarding radius */ }; \ No newline at end of file diff --git a/src/domain/zbmessage/gp-pairing-command-option-struct.cpp b/src/domain/zbmessage/gp-pairing-command-option-struct.cpp index 5ba1c664..cf8d35a1 100644 --- a/src/domain/zbmessage/gp-pairing-command-option-struct.cpp +++ b/src/domain/zbmessage/gp-pairing-command-option-struct.cpp @@ -25,10 +25,7 @@ CGpPairingCommandOption::CGpPairingCommandOption(CEmberGpSinkTableOption i_sink_ } -/** - * @brief option getter - */ -uint32_t CGpPairingCommandOption::get(void) +uint32_t CGpPairingCommandOption::get() const { uint32_t lo_option = 0; diff --git a/src/domain/zbmessage/gp-pairing-command-option-struct.h b/src/domain/zbmessage/gp-pairing-command-option-struct.h index 31e0b9c1..c8a59e6d 100644 --- a/src/domain/zbmessage/gp-pairing-command-option-struct.h +++ b/src/domain/zbmessage/gp-pairing-command-option-struct.h @@ -33,7 +33,7 @@ class CGpPairingCommandOption CGpPairingCommandOption(const CGpPairingCommandOption& other) = delete; /** - * @brief constructor based on sink table entry option field + * @brief Constructor based on sink table entry option field * * @param i_sink_table_option * @param i_add_sink : true to add, false to remove @@ -49,55 +49,57 @@ class CGpPairingCommandOption bool i_key_present, bool i_radius_present ); /** - * @brief option getter + * @brief Option getter + * + * @return This GP pairing command option represented as a 32-bit word */ - uint32_t get(void); + uint32_t get() const; private: /** - * Bit 0..2: The ApplicationID sub-field contains t 3388 he information about the application used by the GPD. + * Bit 0..2: The ApplicationID sub-field contains the information about the application used by the GPD. * ApplicationID = 0b000 indicates the GPD ID field has the length of 4B and contains the GPD SrcID; the Endpoint field is absent. * ApplicationID = 0b010 indicates the GPD ID field has the length of 8B and contains the GPD IEEE address; the Endpoint field is present. * All values of ApplicationID other than 0b000 and 0b010 are reserved in the current version of the Green Power cluster specification. */ - uint8_t application_id; + uint8_t application_id; /*!< The ApplicationID value (contains the information about the application used by the GPD) */ /** * Bit 3: The AddSink sub-field of the Options field indicates, whether the GP sink wishes to add or remove a * pairing for the GPD identified by the GPD ID. If set to 0b1 the pairing is being added. If set to 0b0 the * pairing is being removed; then, the following fields are not present: DeviceID, GPD security Frame * Counter, GPD key, AssignedAlias, and ForwardingRadius. */ - bool add_sink; + bool add_sink; /*!< The AddSink value of the Options field. Indicates, whether the GP sink wishes to add or remove a pairing for the GPD identified by the GPD ID */ /** * Bit 4: The RemoveGPD sub-field of the Options field, if set to 0b1, indicates that the GPD identified by the * GPD ID is being removed from the network. Then, none of the optional fields is present. */ - bool remove_gpd; + bool remove_gpd; /*!< The RemoveGPD sub-field of the Options field, true indicates that the GPD identified by the */ /** * Bit 5..6: The Communication mode sub-field defines the communication mode requested by the sink, and can take values as defined in Table 27. */ - uint8_t communication_mode; + uint8_t communication_mode; /*!< The Communication mode sub-field defines the communication mode requested by the sink */ /** * Bit 7: The GPDfixed sub-field and GPD MAC sequence number capabilities sub-field is copied from the corresponding * FixedLocation and Sequence number capabilities sub-fields of the Options parameter of the Sink Table for this GPD. */ - bool gpd_fixed; + bool gpd_fixed; /*!< The GPDfixed sub-field value */ /** - * Bit 8: see upper + * Bit 8: see above */ - bool gpd_mac_seq_number_capability; + bool gpd_mac_seq_number_capability; /*!< The GPD MAC sequence number capabilities sub-field */ /** * Bit 9..10: The SecurityLevel and SecurityKeyType SHALL carry the values of the corresponding parameters in Sink Table entry for this GPD. */ - uint8_t security_level; + uint8_t security_level; /*!< The SecurityLevel for this GDP command */ /** * Bit 11..13: The sub-fields GPDsecurityFrameCounterPresent and GPDsecurityKeyPresent, if set to 0b1, indicate the presence of the fields * GPDsecurityFrameCounter and GPDsecurityKey, respectively, which then carry the corresponding values from the Sink Table for this GPD. * When the sub-fields GPDsecurityFrameCounterPresent and GPDsecurityKeyPresent are set to 0b0, * the fields GPDsecurityFrame-Counter and GPDsecurityKey, respectively, are not present. */ - uint8_t security_key_type; + uint8_t security_key_type; /*!< The SecurityKeyType for this GDP command */ /** * Bit 14: The GPDsecurityFrameCounter field SHALL be present whenever the AddSink sub-field of the Options field is set to 0b1; * independent of the security level. If the SecurityLevel sub-field is set to 0b10-0b11 or if the SecurityLevel is 0b00 and @@ -105,16 +107,16 @@ class CGpPairingCommandOption * the GPD security frame counter field from the Sink Table entry corresponding to the GPD ID. If the SecurityLevel is 0b00 and * the GPD MAC sequence number capabilities sub-field is set to 0b0, the GPDsecurityFrameCounter SHALL be set to 0b00000000. */ - bool gpd_security_frame_counter_present; + bool gpd_security_frame_counter_present; /*!< Represents whether the GPD security frame counter is present in this GDP command */ /** - * Bit 15: see upper + * Bit 15: see above */ - bool gpd_security_key_present; + bool gpd_security_key_present; /*!< Represents whether the GPD security key is present in this GDP command */ /** * Bit 16: The AssignedAlias present sub-field, if set to 0b1, indicates that the AssignedAlias field is present and * carries the Alias value to be used for this GPD instead of the derived alias. */ - bool assigned_alias_present; + bool assigned_alias_present; /*!< Represents whether the AssignedAlias field is present and carries the Alias value to be used for this GPD instead of the derived alias */ /** * Bit 17: The Forwarding Radius present sub-field, if set to 0b1, indicates that the Forwarding Radius field is * present and carries the Forwarding Radius value to be used as value of the radius in the groupcast forwarding @@ -122,7 +124,7 @@ class CGpPairingCommandOption * the default value of 0x00 SHALL be used. The value 0x00 indicates unspecified, * i.e. twice the value of the nwkMaxDepth attribute of the NIB, as specified by [1]. */ - bool forwarding_radius_present; + bool forwarding_radius_present; /*!< Represents whether the Forwarding Radius sub-field is present in this GDP command */ /** * Bit 18..23: Reserved */ diff --git a/src/domain/zbmessage/gpd-commissioning-command-payload.cpp b/src/domain/zbmessage/gpd-commissioning-command-payload.cpp index d7aa4f36..0f534f87 100644 --- a/src/domain/zbmessage/gpd-commissioning-command-payload.cpp +++ b/src/domain/zbmessage/gpd-commissioning-command-payload.cpp @@ -1,7 +1,7 @@ /** - * @file gpd-commissioning-payload.cpp + * @file gpd-commissioning-command-payload.cpp * - * @brief + * @brief Decoding payload of gpd commissioning command according to A.4.2.1.1 GPD Commissioning command from docs-14-0563-16-batt-green-power-spec_ProxyBasic.pdf */ #include @@ -12,11 +12,6 @@ #include "../custom-aes.h" #include "gpd-commissioning-command-payload.h" -/** - * @brief Construction from an incoming ezsp raw message - * - * @param raw_message The buffer to construct from - */ CGpdCommissioningPayload::CGpdCommissioningPayload(const std::vector& raw_message, uint32_t i_src_id): device_id(raw_message.at(0)), options(raw_message.at(1)), diff --git a/src/domain/zbmessage/gpd-commissioning-command-payload.h b/src/domain/zbmessage/gpd-commissioning-command-payload.h index 908b27a2..e448711d 100644 --- a/src/domain/zbmessage/gpd-commissioning-command-payload.h +++ b/src/domain/zbmessage/gpd-commissioning-command-payload.h @@ -1,7 +1,7 @@ /** * @file gpd-commissionning-command-payload.h * - * @brief decoding payload of gpd commissioning command according to A.4.2.1.1 GPD Commissioning command from docs-14-0563-16-batt-green-power-spec_ProxyBasic.pdf + * @brief Decoding payload of gpd commissioning command according to A.4.2.1.1 GPD Commissioning command from docs-14-0563-16-batt-green-power-spec_ProxyBasic.pdf */ #pragma once @@ -46,7 +46,7 @@ class CGpdCommissioningPayload /** * @brief Assignment operator * - * Copy construction is forbidden on this class + * Assignment is forbidden on this class */ CGpdCommissioningPayload& operator=(const CGpdCommissioningPayload& other) = delete; @@ -54,23 +54,23 @@ class CGpdCommissioningPayload * @brief Construction from an incoming ezsp raw message * * @param raw_message The buffer to construct from - * @param i_src_id source id of gpd frame, use to decrypt key + * @param i_src_id source id of gpd frame, used to decrypt key */ CGpdCommissioningPayload(const std::vector& raw_message, uint32_t i_src_id); /** - * @brief Getter key + * @brief Getter for the enclosed encryption/authentication key * - * @return key + * @return The enclosed key */ - EmberKeyData getKey(){ return key; } + EmberKeyData getKey() const { return key; } /** - * @brief Getter + * @brief Getter for the enclosed device ID * - * @return deviceId + * @return The enclosed deviceId */ - uint8_t getDeviceId(){ return device_id; } + uint8_t getDeviceId() const { return device_id; } // bits field: // b0 : MACsequenceNumberCapability (0b1:incremental MAC sequence number, 0b0:random MAC sequence number) @@ -84,27 +84,27 @@ class CGpdCommissioningPayload /** * @brief options getters bit field */ - bool isMACsequenceNumberCapability(){ return (options & (1< gpd_command_list; - std::vector gpd_cluster_list; + uint8_t app_information; /*!< The app information contained in this GPD commissioning command */ + uint16_t manufacturer_id; /*!< The manufacturer ID contained in this GPD commissioning command */ + uint16_t model_id; /*!< The model ID contained in this GPD commissioning command */ + std::vector gpd_command_list; /*!< The GPD command list contained in this GPD commissioning command */ + std::vector gpd_cluster_list; /*!< The GPD cluster list contained in this GPD commissioning command */ }; \ No newline at end of file diff --git a/src/domain/zbmessage/green-power-frame.h b/src/domain/zbmessage/green-power-frame.h index 1410b9b8..e246582a 100644 --- a/src/domain/zbmessage/green-power-frame.h +++ b/src/domain/zbmessage/green-power-frame.h @@ -33,7 +33,7 @@ class CGpFrame * * Construction without arguments is not allowed */ - CGpFrame(); // = delete; + CGpFrame(); /** * @brief Assignment operator @@ -67,19 +67,18 @@ class CGpFrame friend std::ostream& operator<< (std::ostream& out, const CGpFrame& data); // getter - uint8_t getLinkValue(){return link_value;} - uint8_t getSequenceNumber(){return sequence_number;} - uint32_t getSourceId(){return source_id;} - EGpSecurityLevel getSecurity(){return security;} - EGpSecurityKeyType getKeyType(){return key_type;} - bool isAutoCommissioning(){return auto_commissioning;} - bool isRxAfterTx(){return rx_after_tx;} - uint32_t getSecurityFrameCounter(){return security_frame_counter;} - uint8_t getCommandId(){return command_id;} - uint32_t getMic(){return mic;} - uint8_t getProxyTableEntry(){return proxy_table_entry;} - std::vector getPayload(){return payload;} - + uint8_t getLinkValue() const {return link_value;} + uint8_t getSequenceNumber() const {return sequence_number;} + uint32_t getSourceId() const {return source_id;} + EGpSecurityLevel getSecurity() const {return security;} + EGpSecurityKeyType getKeyType() const {return key_type;} + bool isAutoCommissioning() const {return auto_commissioning;} + bool isRxAfterTx() const {return rx_after_tx;} + uint32_t getSecurityFrameCounter() const {return security_frame_counter;} + uint8_t getCommandId() const {return command_id;} + uint32_t getMic() const {return mic;} + uint8_t getProxyTableEntry() const {return proxy_table_entry;} + std::vector getPayload() const {return payload;} private: uint8_t link_value; diff --git a/src/domain/zbmessage/zigbee-message.cpp b/src/domain/zbmessage/zigbee-message.cpp index 806b3294..9846c1cb 100644 --- a/src/domain/zbmessage/zigbee-message.cpp +++ b/src/domain/zbmessage/zigbee-message.cpp @@ -26,18 +26,6 @@ CZigBeeMsg::~CZigBeeMsg() { } -/** - * @brief SetSpecific : build a basic cluster specific message - * @param i_profile_id : identifier of ZigBee profile to use - * @param i_manufacturer_code : set to 0xFFFF if public cluster - * @param i_endpoint : destination endpoint - * @param i_cluster_id : concerned cluster - * @param i_cmd_id : command - * @param i_direction : model side - * @param i_payload : payload of command - * @param i_src_ieee : address ieee to use as source of message - * @param i_grp_id : multicast group address to use (0 is assume as unicast/broadcast) - */ void CZigBeeMsg::SetSpecific( const uint16_t i_profile_id, const uint16_t i_manufacturer_code, const uint8_t i_endpoint, const uint16_t i_cluster_id, const uint8_t i_cmd_id, const EZCLFrameCtrlDirection i_direction, const std::vector& i_payload, const uint64_t i_src_ieee, const uint8_t i_transaction_number, const uint16_t i_grp_id ) @@ -51,17 +39,6 @@ void CZigBeeMsg::SetSpecific( const uint16_t i_profile_id, const uint16_t i_manu payload = i_payload; } -/** - * @brief SetGeneral : build a basic cluster general message - * @param i_msp_nwk : indicate if it's an msp or public message - * @param i_endpoint : destination endpoint - * @param i_cluster_id : concerned cluster - * @param i_cmd_id : command - * @param i_direction : model side - * @param i_payload : payload of command - * @param i_src_ieee : address ieee to use as source of message - * @param i_grp_id : multicast group address to use (0 is assume as unicast/broadcast) - */ void CZigBeeMsg::SetGeneral(const uint16_t i_profile_id, const uint16_t i_manufacturer_code, const uint8_t i_endpoint, const uint16_t i_cluster_id, const uint8_t i_cmd_id, const EZCLFrameCtrlDirection i_direction, const std::vector& i_payload , const uint64_t i_src_ieee, const uint8_t i_transaction_number, const uint16_t i_grp_id) @@ -75,12 +52,6 @@ void CZigBeeMsg::SetGeneral(const uint16_t i_profile_id, const uint16_t i_manufa payload = i_payload; } -/** - * @brief CZigBeeMsg::SetZdo : fill a ZDO message - * @param i_cmd_id : ZDO command - * @param i_payload : payload for command - * @param i_transaction_number : transaction sequence number - */ void CZigBeeMsg::SetZdo(const uint16_t i_cmd_id, const std::vector& i_payload, const uint8_t i_transaction_number) { aps.SetDefaultAPS( 0x0000, i_cmd_id, 0x00 ); @@ -92,12 +63,6 @@ void CZigBeeMsg::SetZdo(const uint16_t i_cmd_id, const std::vector& i_p payload.insert( payload.begin(), i_transaction_number ); } - -/** - * @brief Set : parse an incomming raw EZSP message - * @param i_aps : aps data - * @param i_msg : message data included header (ZCL and/or MSP) - */ void CZigBeeMsg::Set(const std::vector& i_aps, const std::vector& i_msg ) { uint8_t l_idx = 0; @@ -124,10 +89,6 @@ void CZigBeeMsg::Set(const std::vector& i_aps, const std::vector CZigBeeMsg::Get( void ) const { std::vector lo_msg; @@ -163,5 +124,3 @@ CZigBeeMsg& CZigBeeMsg::operator=(CZigBeeMsg other) swap(*this, other); return *this; } - - diff --git a/src/domain/zbmessage/zigbee-message.h b/src/domain/zbmessage/zigbee-message.h index 65b73b57..a3df0661 100644 --- a/src/domain/zbmessage/zigbee-message.h +++ b/src/domain/zbmessage/zigbee-message.h @@ -119,7 +119,7 @@ class CZigBeeMsg // high level /** - * @brief SetSpecific : build a basic cluster specific message + * @brief Build a basic cluster specific message * @param i_msp_nwk : indicate if it's an msp or public message * @param i_endpoint : destination endpoint * @param i_cluster_id : concerned cluster @@ -134,7 +134,7 @@ class CZigBeeMsg const uint8_t i_transaction_number = 0, const uint16_t i_grp_id = 0); /** - * @brief SetGeneral : build a basic cluster general message + * @brief Build a basic cluster general message * @param i_msp_nwk : indicate if it's an msp or public message * @param i_endpoint : destination endpoint * @param i_cluster_id : concerned cluster @@ -149,25 +149,36 @@ class CZigBeeMsg const uint8_t i_transaction_number = 0, const uint16_t i_grp_id = 0 ); /** - * @brief CZigBeeMsg::SetZdo : fill a ZDO message + * @brief Fill a ZDO message * @param i_cmd_id : ZDO command * @param i_payload : payload for command * @param i_transaction_number : transaction sequence number */ void SetZdo(const uint16_t i_cmd_id, const std::vector& i_payload, const uint8_t i_transaction_number = 0); - // aps - CAPSFrame GetAps(void) const { return aps; } + /** + * @brief Getter for the enclosed APS frame + * + * @return The enclosed APS frame + */ + CAPSFrame GetAps() const { return aps; } - // ZCL Header - CZCLHeader GetZCLHeader(void) const { return zcl_header; } + /** + * @brief Getter for the enclosed ZCL header + * + * @return The enclosed ZCL header + */ + CZCLHeader GetZCLHeader() const { return zcl_header; } - // payload - std::vector GetPayload(void) const { return payload; } + /** + * @brief Getter for the enclosed payload + * + * @return The enclosed payload + */ + std::vector GetPayload() const { return payload; } - // concatenate /** - * @brief Set : parse an incomming raw EZSP message + * @brief Parse an incomming raw EZSP message * @param i_aps : aps data * @param i_msg : message data included header (ZCL and/or MSP) */ @@ -175,23 +186,16 @@ class CZigBeeMsg /** * @brief Get : format zigbee message frame with header - * @return return zigbee message with header + * @return Zigbee message with header */ - std::vector Get( void ) const; + std::vector Get() const; -/*-- TEST GREEN POWER */ - /** APS */ - CAPSFrame aps; + /* FIXME: make the atribute below private as create getter/setter methods */ + CAPSFrame aps; /*!< Enclosed APS frame */ private: - - /** ZCL Header */ - CZCLHeader zcl_header; - - /** Do we have a valid content in attribute zcl_header? */ - bool use_zcl_header; - - /** Payload */ - std::vector payload; + CZCLHeader zcl_header; /*!< Enclosed ZCL header */ + bool use_zcl_header; /*!< Do we have a valid content in attribute zcl_header? */ + std::vector payload; /*!< Enclosed payload */ }; #ifdef USE_RARITAN diff --git a/src/domain/zigbee-tools/green-power-sink.cpp b/src/domain/zigbee-tools/green-power-sink.cpp index 3434a070..0c76bd5b 100644 --- a/src/domain/zigbee-tools/green-power-sink.cpp +++ b/src/domain/zigbee-tools/green-power-sink.cpp @@ -1,5 +1,7 @@ /** * @file green-power-sink.cpp + * + * @brief Access to green power capabilities */ #include @@ -73,7 +75,7 @@ CGpSink::CGpSink( CEzspDongle &i_dongle, CZigbeeMessaging &i_zb_messaging ) : dongle.registerObserver(this); } -void CGpSink::init(void) +void CGpSink::init() { // initialize green power sink clogD << "Call EZSP_GP_SINK_TABLE_INIT" << std::endl; @@ -83,16 +85,13 @@ void CGpSink::init(void) setSinkState(SINK_READY); } -/** - * Clear all GP tables - */ -void CGpSink::gpClearAllTables( void ) +void CGpSink::gpClearAllTables() { // sink table dongle.sendCommand(EZSP_GP_SINK_TABLE_CLEAR_ALL); } -void CGpSink::openCommissioningSession(void) +void CGpSink::openCommissioningSession() { // set local proxy in commissioning mode sendLocalGPProxyCommissioningMode(0x05); @@ -101,7 +100,7 @@ void CGpSink::openCommissioningSession(void) setSinkState(SINK_COM_OPEN); } -void CGpSink::closeCommissioningSession(void) +void CGpSink::closeCommissioningSession() { // set local proxy in commissioning mode sendLocalGPProxyCommissioningMode(0x00); @@ -501,9 +500,6 @@ void CAppDemo::gpSinkTableLookup( uint32_t i_src_id ) } */ -/** - * Finds or allocates a sink entry - */ void CGpSink::gpSinkTableFindOrAllocateEntry( uint32_t i_src_id ) { // An EmberGpAddress struct containing a copy of the gpd address to be found. @@ -513,9 +509,6 @@ void CGpSink::gpSinkTableFindOrAllocateEntry( uint32_t i_src_id ) dongle.sendCommand(EZSP_GP_SINK_TABLE_FIND_OR_ALLOCATE_ENTRY,l_gp_address.getRaw()); } -/** - * Retrieves the sink table entry stored at the passed index. - */ void CGpSink::gpSinkGetEntry( uint8_t i_index ) { std::vector l_payload; @@ -528,12 +521,6 @@ void CGpSink::gpSinkGetEntry( uint8_t i_index ) } -/** - * @brief Retrieves the sink table entry stored at the passed index. - * - * @param i_index The index of the requested sink table entry. - * @param i_entry An EmberGpSinkTableEntry struct containing a copy of the sink entry to be updated. - */ void CGpSink::gpSinkSetEntry( uint8_t i_index, CEmberGpSinkTableEntryStruct& i_entry ) { std::vector l_payload; @@ -550,9 +537,6 @@ void CGpSink::gpSinkSetEntry( uint8_t i_index, CEmberGpSinkTableEntryStruct& i_e } -/** - * Update the GP Proxy table based on a GP pairing. - */ void CGpSink::gpProxyTableProcessGpPairing( CProcessGpPairingParam& i_param ) { clogI << "EZSP_GP_PROXY_TABLE_PROCESS_GP_PAIRING\n"; @@ -560,13 +544,6 @@ void CGpSink::gpProxyTableProcessGpPairing( CProcessGpPairingParam& i_param ) } - - - - -/** - * utility function can managed error state - */ void CGpSink::setSinkState( ESinkState i_state ) { sink_state = i_state; diff --git a/src/domain/zigbee-tools/green-power-sink.h b/src/domain/zigbee-tools/green-power-sink.h index 48ce670c..b9d8c284 100644 --- a/src/domain/zigbee-tools/green-power-sink.h +++ b/src/domain/zigbee-tools/green-power-sink.h @@ -1,7 +1,9 @@ /** * @file green-power-sink.h - * @brief access to green power capabilities + * + * @brief Access to green power capabilities */ + #pragma once #include "../zbmessage/green-power-frame.h" @@ -39,22 +41,22 @@ class CGpSink : public CEzspDongleObserver /** * @brief Initialize sink, shall be done after a network init. */ - void init(void); + void init(); /** * Clear all GP tables */ - void gpClearAllTables( void ); + void gpClearAllTables(); /** * @brief Open a commissioning session for limited time, close as soon as a binding is done. */ - void openCommissioningSession(void); + void openCommissioningSession(); /** * @brief Force to close commissioning session */ - void closeCommissioningSession(void); + void closeCommissioningSession(); /** * @brief add a green power sink table entry @@ -91,35 +93,43 @@ class CGpSink : public CEzspDongleObserver uint8_t sink_table_index; CEmberGpSinkTableEntryStruct sink_table_entry; + std::set observers; /*!< List of observers of this class */ + /** - * Notify Observer of this class + * @brief Notify observers of this class + * + * @param i_gpf The received GP frame */ - std::set observers; void notifyObserversOfRxGpFrame( CGpFrame i_gpf ); + /** + * @brief Private utility function to manage error state + */ void setSinkState( ESinkState i_state ); /** * @brief send zigbee unicast message GP Proxy Commissioning Mode. - * done from sink to local dongle. - * WARNING all parameters are hardcoded for testing + * done from sink to local dongle. + * @warning All parameters are hardcoded for testing */ void sendLocalGPProxyCommissioningMode(uint8_t i_option); /** - * Retrieves the sink table entry stored at the passed index. + * @brief Retrieves the sink table entry stored at the specified index + * + * @param i_index The index to lookup */ void gpSinkGetEntry( uint8_t i_index ); /** * @brief Finds or allocates a sink entry * - * @param i_src_id : gpd address to be found + * @param i_src_id GPD source ID address to search */ void gpSinkTableFindOrAllocateEntry( uint32_t i_src_id ); /** - * @brief Retrieves the sink table entry stored at the passed index. + * @brief Updates the sink table entry at the specified index. * * @param i_index The index of the requested sink table entry. * @param i_entry An EmberGpSinkTableEntry struct containing a copy of the sink entry to be updated. @@ -127,7 +137,7 @@ class CGpSink : public CEzspDongleObserver void gpSinkSetEntry( uint8_t i_index, CEmberGpSinkTableEntryStruct& i_entry ); /** - * Update the GP Proxy table based on a GP pairing. + * @brief Update the GP Proxy table based on a GP pairing. */ void gpProxyTableProcessGpPairing( CProcessGpPairingParam& i_param ); }; diff --git a/src/example/mainEzspTest.cpp b/src/example/mainEzspTest.cpp index fb3a785d..f2d48a89 100644 --- a/src/example/mainEzspTest.cpp +++ b/src/example/mainEzspTest.cpp @@ -45,7 +45,7 @@ int main(int argc, char **argv) { SerialUartDriver uartDriver; CppThreadsTimerFactory timerFactory; - ConsoleLogger::getInstance().setLogLevel(LOG_LEVEL::TRACE); /* Only display logs for debug level info and higher (up to error) */ + ConsoleLogger::getInstance().setLogLevel(LOG_LEVEL::INFO); /* Only display logs for debug level info and higher (up to error) */ #endif #ifdef USE_RARITAN RaritanEventLoop eventLoop; From 851082c6974e4a3ed57d5fbee59bd0d770f8e068 Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 21 Nov 2019 14:45:07 +0100 Subject: [PATCH 26/44] adding code value when ember status is out of range --- src/domain/ezsp-protocol/ezsp-enum.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/domain/ezsp-protocol/ezsp-enum.cpp b/src/domain/ezsp-protocol/ezsp-enum.cpp index 25feea90..7b227254 100644 --- a/src/domain/ezsp-protocol/ezsp-enum.cpp +++ b/src/domain/ezsp-protocol/ezsp-enum.cpp @@ -43,7 +43,7 @@ std::string CEzspEnum::EEmberStatusToString( EEmberStatus in ) { EMBER_NO_NETWORK_KEY_RECEIVED, "EMBER_NO_NETWORK_KEY_RECEIVED" } }; auto it = MyEnumStrings.find(in); - return it == MyEnumStrings.end() ? "OUT_OF_RANGE" : it->second; + return it == MyEnumStrings.end() ? "OUT_OF_RANGE : " + std::to_string(in) : it->second; } std::string CEzspEnum::EmberJoinMethodToString( EmberJoinMethod in ) From 323de9ced1e47da28a7b715b208b006ec68fdffa Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 21 Nov 2019 14:46:00 +0100 Subject: [PATCH 27/44] register an hardcoded gpd if we do not request to open gpd commissioning for debug --- src/example/CAppDemo.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/example/CAppDemo.cpp b/src/example/CAppDemo.cpp index e24c555f..7e64b6a8 100644 --- a/src/example/CAppDemo.cpp +++ b/src/example/CAppDemo.cpp @@ -280,6 +280,12 @@ void CAppDemo::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_r // If requested to do so, immediately open a GP commissioning session gp_sink.openCommissioningSession(); } + else + { + // debug : add hardcoded gpd + gp_sink.registerGpd(0x00510050,{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F}); + } + if (this->openZigbeeCommissionningAtStartup) { // If requested to do so, open the zigbee network for a specific duration, so new devices can join From d307575340d6b3b4c94fcde3ef42949c3e11de45 Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 21 Nov 2019 14:46:18 +0100 Subject: [PATCH 28/44] prepare state machine for offline commissioning --- src/domain/zigbee-tools/green-power-sink.cpp | 5 +++++ src/domain/zigbee-tools/green-power-sink.h | 1 + 2 files changed, 6 insertions(+) diff --git a/src/domain/zigbee-tools/green-power-sink.cpp b/src/domain/zigbee-tools/green-power-sink.cpp index 3434a070..e7a7a29c 100644 --- a/src/domain/zigbee-tools/green-power-sink.cpp +++ b/src/domain/zigbee-tools/green-power-sink.cpp @@ -119,7 +119,12 @@ uint8_t CGpSink::registerGpd( uint32_t i_source_id ) void CGpSink::registerGpd( uint32_t i_source_id, std::vector i_key ) { + // save offline information + + // request sink table entry + // set state + setSinkState(SINK_COM_OFFLINE_IN_PROGRESS); } void CGpSink::handleDongleState( EDongleState i_state ) diff --git a/src/domain/zigbee-tools/green-power-sink.h b/src/domain/zigbee-tools/green-power-sink.h index 48ce670c..a855aeca 100644 --- a/src/domain/zigbee-tools/green-power-sink.h +++ b/src/domain/zigbee-tools/green-power-sink.h @@ -24,6 +24,7 @@ typedef enum SINK_ERROR, // something wrong SINK_COM_OPEN, // GP Proxy Commissioning mode open SINK_COM_IN_PROGRESS, // GP sink receive gpf comm frame + SINK_COM_OFFLINE_IN_PROGRESS, // Doing offline commissioning for GPD list }ESinkState; class CGpSink : public CEzspDongleObserver From 68d3840ce6e9461e070be20bf426f3eb8f132c5c Mon Sep 17 00:00:00 2001 From: seb Date: Thu, 21 Nov 2019 15:47:51 +0100 Subject: [PATCH 29/44] offline commissioning work with very few hardcoded value --- src/domain/zigbee-tools/green-power-sink.cpp | 66 +++++++++++++++++++- 1 file changed, 65 insertions(+), 1 deletion(-) diff --git a/src/domain/zigbee-tools/green-power-sink.cpp b/src/domain/zigbee-tools/green-power-sink.cpp index 13567337..8e1d42cc 100644 --- a/src/domain/zigbee-tools/green-power-sink.cpp +++ b/src/domain/zigbee-tools/green-power-sink.cpp @@ -119,8 +119,12 @@ uint8_t CGpSink::registerGpd( uint32_t i_source_id ) void CGpSink::registerGpd( uint32_t i_source_id, std::vector i_key ) { // save offline information + CEmberGpAddressStruct l_gp_addr(i_source_id); + sink_table_entry.setGpdAddress(l_gp_addr); + sink_table_entry.setKey(i_key); // request sink table entry + gpSinkTableFindOrAllocateEntry( i_source_id ); // set state setSinkState(SINK_COM_OFFLINE_IN_PROGRESS); @@ -194,6 +198,12 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re } else { + // if success notify + if( EEmberStatus::EMBER_SUCCESS == l_status ) + { + notifyObserversOfRxGpFrame( gpf ); + } + /* // look up if product is register uint8_t l_sink_entry_idx = sink_table.getEntryIndexForSourceId( gpf.getSourceId() ); if( GP_SINK_INVALID_ENTRY != l_sink_entry_idx ) @@ -201,6 +211,7 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re // to test notify notifyObserversOfRxGpFrame( gpf ); } + */ } } break; @@ -215,6 +226,26 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re // debug clogD << "EZSP_GP_SINK_TABLE_FIND_OR_ALLOCATE_ENTRY response index : " << std::hex << std::setw(2) << std::setfill('0') << sink_table_index << std::endl; + // retrieve entry at selected index + if( 0xFF != sink_table_index ) + { + gpSinkGetEntry( sink_table_index ); + } + else + { + // no place to done pairing : FAILED + clogD << "INVALID SINK TABLE ENTRY, PAIRING FAILED !!" << std::endl; + setSinkState(SINK_READY); + } + } + else if( SINK_COM_OFFLINE_IN_PROGRESS == sink_state ) + { + // save allocate index + sink_table_index = i_msg_receive.at(0); + + // debug + clogD << "EZSP_GP_SINK_TABLE_FIND_OR_ALLOCATE_ENTRY response index : " << std::hex << std::setw(2) << std::setfill('0') << sink_table_index << std::endl; + // retrieve entry at selected index if( 0xFF != sink_table_index ) { @@ -265,6 +296,32 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re // call gpSinkSetEntry(sink_table_index,l_entry); + // save + sink_table_entry = l_entry; + } + else if( SINK_COM_OFFLINE_IN_PROGRESS == sink_state ) + { + EEmberStatus l_status = static_cast(i_msg_receive.at(0)); + CEmberGpSinkTableEntryStruct l_entry({i_msg_receive.begin()+1,i_msg_receive.end()}); + + // debug + clogD << "EZSP_GP_SINK_TABLE_GET_ENTRY Response status :" << CEzspEnum::EEmberStatusToString(l_status) << ", table entry : " << l_entry << std::endl; + + // update sink table entry + l_entry.setEntryActive(true); + l_entry.setOptions(0x02A8); // \todo WARNING HARDCODED VALUE + l_entry.setGpdAddress(sink_table_entry.getGpdAddr()); + l_entry.setAlias(static_cast(sink_table_entry.getGpdAddr().getSourceId()&0xFFFF)); + l_entry.setSecurityOption(0x12); // \todo WARNING HARDCODED VALUE + l_entry.setFrameCounter(0); + l_entry.setKey(sink_table_entry.getGpdKey()); + + // debug + clogD << "Update table entry : " << l_entry << std::endl; + + // call + gpSinkSetEntry(sink_table_index,l_entry); + // save sink_table_entry = l_entry; } @@ -273,7 +330,7 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re case EZSP_GP_SINK_TABLE_SET_ENTRY: { - if( SINK_COM_IN_PROGRESS == sink_state ) + if( (SINK_COM_IN_PROGRESS == sink_state) || (SINK_COM_OFFLINE_IN_PROGRESS == sink_state) ) { EEmberStatus l_status = static_cast(i_msg_receive.at(0)); @@ -307,6 +364,13 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re // close commissioning session closeCommissioningSession(); } + else if( SINK_COM_OFFLINE_IN_PROGRESS == sink_state ) + { + clogI << "CGpSink::ezspHandler EZSP_GP_PROXY_TABLE_PROCESS_GP_PAIRING gpPairingAdded : " << std::hex << std::setw(2) << std::setfill('0') << static_cast(i_msg_receive[0]) << std::endl; + + // set state + setSinkState(SINK_READY); + } } break; From 97efc764ff9f934a3343218d1e86de958f66e830 Mon Sep 17 00:00:00 2001 From: Lionel AINS Date: Thu, 21 Nov 2019 16:11:36 +0100 Subject: [PATCH 30/44] Upgrading doxygen conf --- Doxyfile.dev | 554 ++++++++++++++++++++++++++++++++------------------- 1 file changed, 346 insertions(+), 208 deletions(-) diff --git a/Doxyfile.dev b/Doxyfile.dev index 81f27122..9333a55b 100644 --- a/Doxyfile.dev +++ b/Doxyfile.dev @@ -1,4 +1,4 @@ -# Doxyfile 1.8.6 +# Doxyfile 1.8.13 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. @@ -32,7 +32,7 @@ DOXYFILE_ENCODING = UTF-8 # title of most generated pages and in a few other places. # The default value is: My Project. -PROJECT_NAME = $(PROJECT) +PROJECT_NAME = "libezsp" # The PROJECT_NUMBER tag can be used to enter a project or revision number. This # could be handy for archiving the generated documentation or if some version @@ -44,14 +44,14 @@ PROJECT_NUMBER = $(VERSION) # for a project that appears at the top of each page and should give viewer a # quick idea about the purpose of the project. Keep the description short. -PROJECT_BRIEF = "C++ Library to interact with EZSP transceivers" +PROJECT_BRIEF = "C++ library to send/receive wireless Zigbee messages to/from a Silicon Labs-based transceiver using the EZSP protocol." -# With the PROJECT_LOGO tag one can specify an logo or icon that is included in -# the documentation. The maximum height of the logo should not exceed 55 pixels -# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo -# to the output directory. +# With the PROJECT_LOGO tag one can specify a logo or an icon that is included +# in the documentation. The maximum height of the logo should not exceed 55 +# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy +# the logo to the output directory. -PROJECT_LOGO = +PROJECT_LOGO = # The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path # into which the generated documentation will be written. If a relative path is @@ -60,7 +60,7 @@ PROJECT_LOGO = OUTPUT_DIRECTORY = doc -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub- # directories (in 2 levels) under the output directory of each output format and # will distribute the generated files over these directories. Enabling this # option can be useful when feeding doxygen a huge amount of source files, where @@ -70,6 +70,14 @@ OUTPUT_DIRECTORY = doc CREATE_SUBDIRS = NO +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. @@ -85,14 +93,14 @@ CREATE_SUBDIRS = NO OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member # descriptions after the members that are listed in the file and class # documentation (similar to Javadoc). Set to NO to disable this. # The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief # description of a member or function before the detailed description # # Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the @@ -137,7 +145,7 @@ ALWAYS_DETAILED_SEC = NO INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path # before files name in the file list and in the header files. If set to NO the # shortest path that makes the file name unique will be used # The default value is: YES. @@ -154,7 +162,7 @@ FULL_PATH_NAMES = YES # will be relative from the directory where doxygen is started. # This tag requires that the tag FULL_PATH_NAMES is set to YES. -STRIP_FROM_PATH = +STRIP_FROM_PATH = # The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the # path mentioned in the documentation of a class, which tells the reader which @@ -163,7 +171,7 @@ STRIP_FROM_PATH = # specify the list of include paths that are normally passed to the compiler # using the -I flag. -STRIP_FROM_INC_PATH = +STRIP_FROM_INC_PATH = # If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but # less readable) file names. This can be useful is your file systems doesn't @@ -207,9 +215,9 @@ MULTILINE_CPP_IS_BRIEF = NO INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a -# new page for each member. If set to NO, the documentation of a member will be -# part of the file/class/namespace that contains it. +# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new +# page for each member. If set to NO, the documentation of a member will be part +# of the file/class/namespace that contains it. # The default value is: NO. SEPARATE_MEMBER_PAGES = NO @@ -230,13 +238,13 @@ TAB_SIZE = 4 # "Side Effects:". You can put \n's in the value part of an alias to insert # newlines. -ALIASES = +ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). # A mapping has the form "name=value". For example adding "class=itcl::class" # will allow you to use the command class in the itcl::class meaning. -TCL_SUBST = +TCL_SUBST = # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources # only. Doxygen will then generate output that is more tailored for C. For @@ -271,16 +279,19 @@ OPTIMIZE_OUTPUT_VHDL = NO # extension. Doxygen has a built-in mapping, but you can override or extend it # using this tag. The format is ext=language, where ext is a file extension, and # language is one of the parsers supported by doxygen: IDL, Java, Javascript, -# C#, C, C++, D, PHP, Objective-C, Python, Fortran, VHDL. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. # -# Note For files without extension you can use no_extension as a placeholder. +# Note: For files without extension you can use no_extension as a placeholder. # # Note that for custom extensions you also need to set FILE_PATTERNS otherwise # the files are not read by doxygen. -EXTENSION_MAPPING = +EXTENSION_MAPPING = # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments # according to the Markdown format, which allows for more readable @@ -292,10 +303,19 @@ EXTENSION_MAPPING = MARKDOWN_SUPPORT = YES +# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up +# to that level are automatically included in the table of contents, even if +# they do not have an id attribute. +# Note: This feature currently applies only to Markdown headings. +# Minimum value: 0, maximum value: 99, default value: 0. +# This tag requires that the tag MARKDOWN_SUPPORT is set to YES. + +TOC_INCLUDE_HEADINGS = 0 + # When enabled doxygen tries to link words that correspond to documented # classes, or namespaces to their corresponding documentation. Such a link can -# be prevented in individual cases by by putting a % sign in front of the word -# or globally by setting AUTOLINK_SUPPORT to NO. +# be prevented in individual cases by putting a % sign in front of the word or +# globally by setting AUTOLINK_SUPPORT to NO. # The default value is: YES. AUTOLINK_SUPPORT = YES @@ -335,13 +355,20 @@ SIP_SUPPORT = NO IDL_PROPERTY_SUPPORT = YES # If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC -# tag is set to YES, then doxygen will reuse the documentation of the first +# tag is set to YES then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. # The default value is: NO. DISTRIBUTE_GROUP_DOC = NO +# If one adds a struct or class to a group and this option is enabled, then also +# any nested class or struct is added to the same group. By default this option +# is disabled and one has to add nested compounds explicitly via \ingroup. +# The default value is: NO. + +GROUP_NESTED_COMPOUNDS = NO + # Set the SUBGROUPING tag to YES to allow class member groups of the same type # (for instance a group of public functions) to be put as a subgroup of that # type (e.g. under the Public Functions section). Set it to NO to prevent @@ -400,7 +427,7 @@ LOOKUP_CACHE_SIZE = 0 # Build related configuration options #--------------------------------------------------------------------------- -# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in +# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in # documentation are documented, even if no documentation was available. Private # class members and static file members will be hidden unless the # EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. @@ -410,35 +437,35 @@ LOOKUP_CACHE_SIZE = 0 EXTRACT_ALL = NO -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will # be included in the documentation. # The default value is: NO. EXTRACT_PRIVATE = YES -# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal # scope will be included in the documentation. # The default value is: NO. EXTRACT_PACKAGE = NO -# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be # included in the documentation. # The default value is: NO. EXTRACT_STATIC = NO -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined -# locally in source files will be included in the documentation. If set to NO +# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO, # only classes defined in header files are included. Does not have any effect # for Java sources. # The default value is: YES. EXTRACT_LOCAL_CLASSES = YES -# This flag is only useful for Objective-C code. When set to YES local methods, +# This flag is only useful for Objective-C code. If set to YES, local methods, # which are defined in the implementation section but not in the interface are -# included in the documentation. If set to NO only methods in the interface are +# included in the documentation. If set to NO, only methods in the interface are # included. # The default value is: NO. @@ -463,21 +490,21 @@ HIDE_UNDOC_MEMBERS = NO # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all # undocumented classes that are normally visible in the class hierarchy. If set -# to NO these classes will be included in the various overviews. This option has -# no effect if EXTRACT_ALL is enabled. +# to NO, these classes will be included in the various overviews. This option +# has no effect if EXTRACT_ALL is enabled. # The default value is: NO. HIDE_UNDOC_CLASSES = NO # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend -# (class|struct|union) declarations. If set to NO these declarations will be +# (class|struct|union) declarations. If set to NO, these declarations will be # included in the documentation. # The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO # If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any -# documentation blocks found inside the body of a function. If set to NO these +# documentation blocks found inside the body of a function. If set to NO, these # blocks will be appended to the function's detailed documentation block. # The default value is: NO. @@ -491,7 +518,7 @@ HIDE_IN_BODY_DOCS = NO INTERNAL_DOCS = NO # If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file -# names in lower-case letters. If set to YES upper-case letters are also +# names in lower-case letters. If set to YES, upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. @@ -500,12 +527,19 @@ INTERNAL_DOCS = NO CASE_SENSE_NAMES = NO # If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with -# their full class and namespace scopes in the documentation. If set to YES the +# their full class and namespace scopes in the documentation. If set to YES, the # scope will be hidden. # The default value is: NO. HIDE_SCOPE_NAMES = NO +# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will +# append additional text to a page's title, such as Class Reference. If set to +# YES the compound reference will be hidden. +# The default value is: NO. + +HIDE_COMPOUND_REFERENCE= NO + # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of # the files that are included by a file in the documentation of that file. # The default value is: YES. @@ -533,14 +567,14 @@ INLINE_INFO = YES # If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the # (detailed) documentation of file and class members alphabetically by member -# name. If set to NO the members will appear in declaration order. +# name. If set to NO, the members will appear in declaration order. # The default value is: YES. SORT_MEMBER_DOCS = YES # If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief # descriptions of file, namespace and class members alphabetically by member -# name. If set to NO the members will appear in declaration order. Note that +# name. If set to NO, the members will appear in declaration order. Note that # this will also influence the order of the classes in the class list. # The default value is: NO. @@ -585,27 +619,25 @@ SORT_BY_SCOPE_NAME = NO STRICT_PROTO_MATCHING = NO -# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the -# todo list. This list is created by putting \todo commands in the -# documentation. +# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo +# list. This list is created by putting \todo commands in the documentation. # The default value is: YES. GENERATE_TODOLIST = YES -# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the -# test list. This list is created by putting \test commands in the -# documentation. +# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test +# list. This list is created by putting \test commands in the documentation. # The default value is: YES. GENERATE_TESTLIST = YES -# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug # list. This list is created by putting \bug commands in the documentation. # The default value is: YES. GENERATE_BUGLIST = YES -# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO) # the deprecated list. This list is created by putting \deprecated commands in # the documentation. # The default value is: YES. @@ -616,7 +648,7 @@ GENERATE_DEPRECATEDLIST= YES # sections, marked by \if ... \endif and \cond # ... \endcond blocks. -ENABLED_SECTIONS = +ENABLED_SECTIONS = # The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the # initial value of a variable or macro / define can have for it to appear in the @@ -630,8 +662,8 @@ ENABLED_SECTIONS = MAX_INITIALIZER_LINES = 30 # Set the SHOW_USED_FILES tag to NO to disable the list of files generated at -# the bottom of the documentation of classes and structs. If set to YES the list -# will mention the files that were used to generate the documentation. +# the bottom of the documentation of classes and structs. If set to YES, the +# list will mention the files that were used to generate the documentation. # The default value is: YES. SHOW_USED_FILES = YES @@ -658,7 +690,7 @@ SHOW_NAMESPACES = YES # by doxygen. Whatever the program writes to standard output is used as the file # version. For an example see the documentation. -FILE_VERSION_FILTER = +FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated @@ -671,7 +703,7 @@ FILE_VERSION_FILTER = # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE # tag is left empty. -LAYOUT_FILE = +LAYOUT_FILE = # The CITE_BIB_FILES tag can be used to specify one or more bib files containing # the reference definitions. This must be a list of .bib files. The .bib @@ -679,10 +711,9 @@ LAYOUT_FILE = # to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. # For LaTeX the style of the bibliography can be controlled using # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the -# search path. Do not use file names with spaces, bibtex cannot handle them. See -# also \cite for info how to create references. +# search path. See also \cite for info how to create references. -CITE_BIB_FILES = +CITE_BIB_FILES = #--------------------------------------------------------------------------- # Configuration options related to warning and progress messages @@ -696,7 +727,7 @@ CITE_BIB_FILES = QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are -# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES # this implies that the warnings are on. # # Tip: Turn warnings on while writing the documentation. @@ -704,7 +735,7 @@ QUIET = NO WARNINGS = YES -# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate # warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag # will automatically be disabled. # The default value is: YES. @@ -721,12 +752,18 @@ WARN_IF_DOC_ERROR = YES # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that # are documented, but have no documentation for their parameters or return -# value. If set to NO doxygen will only warn about wrong or incomplete parameter -# documentation, but not about the absence of documentation. +# value. If set to NO, doxygen will only warn about wrong or incomplete +# parameter documentation, but not about the absence of documentation. # The default value is: NO. WARN_NO_PARAMDOC = NO +# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when +# a warning is encountered. +# The default value is: NO. + +WARN_AS_ERROR = NO + # The WARN_FORMAT tag determines the format of the warning messages that doxygen # can produce. The string should contain the $file, $line, and $text tags, which # will be replaced by the file and line number from which the warning originated @@ -741,7 +778,7 @@ WARN_FORMAT = "$file:$line: $text" # messages should be written. If left blank the output is written to standard # error (stderr). -WARN_LOGFILE = +WARN_LOGFILE = #--------------------------------------------------------------------------- # Configuration options related to the input files @@ -750,7 +787,7 @@ WARN_LOGFILE = # The INPUT tag is used to specify the files and/or directories that contain # documented source files. You may enter file names like myfile.cpp or # directories like /usr/src/myproject. Separate the files or directories with -# spaces. +# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING # Note: If this tag is empty the current directory is searched. INPUT = ./src @@ -766,12 +803,17 @@ INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and -# *.h) to filter out the source-files in the directories. If left blank the -# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, -# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, -# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, -# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, -# *.qsf, *.as and *.js. +# *.h) to filter out the source-files in the directories. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# read by doxygen. +# +# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp, +# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, +# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, +# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, +# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf. FILE_PATTERNS = *.c \ *.cc \ @@ -829,7 +871,7 @@ RECURSIVE = YES # Note that relative paths are relative to the directory from which doxygen is # run. -EXCLUDE = +EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded @@ -845,7 +887,7 @@ EXCLUDE_SYMLINKS = NO # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories for example use the pattern */test/* -EXCLUDE_PATTERNS = +EXCLUDE_PATTERNS = # The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names # (namespaces, classes, functions, etc.) that should be excluded from the @@ -856,13 +898,13 @@ EXCLUDE_PATTERNS = # Note that the wildcards are matched against the file with absolute path, so to # exclude all test directories use the pattern */test/* -EXCLUDE_SYMBOLS = +EXCLUDE_SYMBOLS = # The EXAMPLE_PATH tag can be used to specify one or more files or directories # that contain example code fragments that are included (see the \include # command). -EXAMPLE_PATH = +EXAMPLE_PATH = # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and @@ -882,7 +924,7 @@ EXAMPLE_RECURSIVE = NO # that contain images that are to be included in the documentation (see the # \image command). -IMAGE_PATH = +IMAGE_PATH = # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program @@ -898,8 +940,12 @@ IMAGE_PATH = # Note that the filter must not add or remove lines; it is applied before the # code is scanned, but not when the output code is generated. If lines are added # or removed, the anchors will not be placed correctly. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. -INPUT_FILTER = +INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern # basis. Doxygen will compare the file name with each pattern and apply the @@ -907,11 +953,15 @@ INPUT_FILTER = # (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how # filters are used. If the FILTER_PATTERNS tag is empty or if none of the # patterns match the file name, INPUT_FILTER is applied. +# +# Note that for custom extensions or not directly supported extensions you also +# need to set EXTENSION_MAPPING for the extension otherwise the files are not +# properly processed by doxygen. -FILTER_PATTERNS = +FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER ) will also be used to filter the input files that are used for +# INPUT_FILTER) will also be used to filter the input files that are used for # producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). # The default value is: NO. @@ -923,14 +973,14 @@ FILTER_SOURCE_FILES = NO # *.ext= (so without naming a filter). # This tag requires that the tag FILTER_SOURCE_FILES is set to YES. -FILTER_SOURCE_PATTERNS = +FILTER_SOURCE_PATTERNS = # If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that # is part of the input, its contents will be placed on the main page # (index.html). This can be useful if you have a project on for instance GitHub # and want to reuse the introduction page also for the doxygen output. -USE_MDFILE_AS_MAINPAGE = +USE_MDFILE_AS_MAINPAGE = #--------------------------------------------------------------------------- # Configuration options related to source browsing @@ -971,7 +1021,7 @@ REFERENCED_BY_RELATION = NO REFERENCES_RELATION = NO # If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set -# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# to YES then the hyperlinks from functions in REFERENCES_RELATION and # REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will # link to the documentation. # The default value is: YES. @@ -1018,6 +1068,25 @@ USE_HTAGS = NO VERBATIM_HEADERS = YES +# If the CLANG_ASSISTED_PARSING tag is set to YES then doxygen will use the +# clang parser (see: http://clang.llvm.org/) for more accurate parsing at the +# cost of reduced performance. This can be particularly helpful with template +# rich C++ code for which doxygen's built-in parser lacks the necessary type +# information. +# Note: The availability of this option depends on whether or not doxygen was +# generated with the -Duse-libclang=ON option for CMake. +# The default value is: NO. + +CLANG_ASSISTED_PARSING = NO + +# If clang assisted parsing is enabled you can provide the compiler with command +# line options that you would normally use when invoking the compiler. Note that +# the include paths will already be set by doxygen for the files and directories +# specified with INPUT and INCLUDE_PATH. +# This tag requires that the tag CLANG_ASSISTED_PARSING is set to YES. + +CLANG_OPTIONS = + #--------------------------------------------------------------------------- # Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- @@ -1042,13 +1111,13 @@ COLS_IN_ALPHA_INDEX = 5 # while generating the index headers. # This tag requires that the tag ALPHABETICAL_INDEX is set to YES. -IGNORE_PREFIX = +IGNORE_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output # The default value is: YES. GENERATE_HTML = YES @@ -1086,7 +1155,7 @@ HTML_FILE_EXTENSION = .html # of the possible markers and block names see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_HEADER = +HTML_HEADER = # The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each # generated HTML page. If the tag is left blank doxygen will generate a standard @@ -1096,7 +1165,7 @@ HTML_HEADER = # that doxygen normally uses. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_FOOTER = +HTML_FOOTER = # The HTML_STYLESHEET tag can be used to specify a user-defined cascading style # sheet that is used by each HTML page. It can be used to fine-tune the look of @@ -1108,18 +1177,20 @@ HTML_FOOTER = # obsolete. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_STYLESHEET = +HTML_STYLESHEET = -# The HTML_EXTRA_STYLESHEET tag can be used to specify an additional user- -# defined cascading style sheet that is included after the standard style sheets +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets # created by doxygen. Using this option one can overrule certain style aspects. # This is preferred over using HTML_STYLESHEET since it does not replace the -# standard style sheet and is therefor more robust against future updates. -# Doxygen will copy the style sheet file to the output directory. For an example -# see the documentation. +# standard style sheet and is therefore more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_STYLESHEET = +HTML_EXTRA_STYLESHEET = # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note @@ -1129,10 +1200,10 @@ HTML_EXTRA_STYLESHEET = # files will be copied as-is; there are no commands or markers available. # This tag requires that the tag GENERATE_HTML is set to YES. -HTML_EXTRA_FILES = +HTML_EXTRA_FILES = # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen -# will adjust the colors in the stylesheet and background images according to +# will adjust the colors in the style sheet and background images according to # this color. Hue is specified as an angle on a colorwheel, see # http://en.wikipedia.org/wiki/Hue for more information. For instance the value # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 @@ -1163,8 +1234,9 @@ HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML # page will contain the date and time when the page was generated. Setting this -# to NO can help when comparing the output of multiple runs. -# The default value is: YES. +# to YES can help to show when doxygen was last run and thus if the +# documentation is up to date. +# The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES @@ -1257,31 +1329,32 @@ GENERATE_HTMLHELP = NO # written to the html output directory. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. -CHM_FILE = +CHM_FILE = # The HHC_LOCATION tag can be used to specify the location (absolute path -# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# including file name) of the HTML help compiler (hhc.exe). If non-empty, # doxygen will try to run the HTML help compiler on the generated index.hhp. # The file has to be specified with full path. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. -HHC_LOCATION = +HHC_LOCATION = -# The GENERATE_CHI flag controls if a separate .chi index file is generated ( -# YES) or that it should be included in the master .chm file ( NO). +# The GENERATE_CHI flag controls if a separate .chi index file is generated +# (YES) or that it should be included in the master .chm file (NO). # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = NO -# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc) # and project file content. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. -CHM_INDEX_ENCODING = +CHM_INDEX_ENCODING = -# The BINARY_TOC flag controls whether a binary table of contents is generated ( -# YES) or a normal table of contents ( NO) in the .chm file. +# The BINARY_TOC flag controls whether a binary table of contents is generated +# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. # The default value is: NO. # This tag requires that the tag GENERATE_HTMLHELP is set to YES. @@ -1308,7 +1381,7 @@ GENERATE_QHP = NO # the HTML output folder. # This tag requires that the tag GENERATE_QHP is set to YES. -QCH_FILE = +QCH_FILE = # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help # Project output. For more information please see Qt Help Project / Namespace @@ -1333,7 +1406,7 @@ QHP_VIRTUAL_FOLDER = doc # filters). # This tag requires that the tag GENERATE_QHP is set to YES. -QHP_CUST_FILTER_NAME = +QHP_CUST_FILTER_NAME = # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the # custom filter to add. For more information please see Qt Help Project / Custom @@ -1341,21 +1414,21 @@ QHP_CUST_FILTER_NAME = # filters). # This tag requires that the tag GENERATE_QHP is set to YES. -QHP_CUST_FILTER_ATTRS = +QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this # project's filter section matches. Qt Help Project / Filter Attributes (see: # http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). # This tag requires that the tag GENERATE_QHP is set to YES. -QHP_SECT_FILTER_ATTRS = +QHP_SECT_FILTER_ATTRS = # The QHG_LOCATION tag can be used to specify the location of Qt's # qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the # generated .qhp file. # This tag requires that the tag GENERATE_QHP is set to YES. -QHG_LOCATION = +QHG_LOCATION = # If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be # generated, together with the HTML files, they form an Eclipse help plugin. To @@ -1394,7 +1467,7 @@ DISABLE_INDEX = NO # index structure (just like the one that is generated for HTML Help). For this # to work a browser that supports JavaScript, DHTML, CSS and frames is required # (i.e. any modern browser). Windows users are probably better off using the -# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can # further fine-tune the look of the index. As an example, the default style # sheet generated by doxygen has an example that shows how to put an image at # the root of the tree instead of the PROJECT_NAME. Since the tree basically has @@ -1422,7 +1495,7 @@ ENUM_VALUES_PER_LINE = 4 TREEVIEW_WIDTH = 250 -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to # external symbols imported via tag files in a separate window. # The default value is: NO. # This tag requires that the tag GENERATE_HTML is set to YES. @@ -1451,7 +1524,7 @@ FORMULA_TRANSPARENT = YES # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see # http://www.mathjax.org) which uses client side Javascript for the rendering -# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX # installed or if you want to formulas look prettier in the HTML output. When # enabled you may also need to install MathJax separately and configure the path # to it using the MATHJAX_RELPATH option. @@ -1488,7 +1561,7 @@ MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols # This tag requires that the tag USE_MATHJAX is set to YES. -MATHJAX_EXTENSIONS = +MATHJAX_EXTENSIONS = # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces # of code that will be used on startup of the MathJax code. See the MathJax site @@ -1496,7 +1569,7 @@ MATHJAX_EXTENSIONS = # example see the documentation. # This tag requires that the tag USE_MATHJAX is set to YES. -MATHJAX_CODEFILE = +MATHJAX_CODEFILE = # When the SEARCHENGINE tag is enabled doxygen will generate a search box for # the HTML output. The underlying search engine uses javascript and DHTML and @@ -1521,11 +1594,11 @@ SEARCHENGINE = YES # When the SERVER_BASED_SEARCH tag is enabled the search engine will be # implemented using a web server instead of a web client using Javascript. There -# are two flavours of web server based searching depending on the -# EXTERNAL_SEARCH setting. When disabled, doxygen will generate a PHP script for -# searching and an index file used by the script. When EXTERNAL_SEARCH is -# enabled the indexing and searching needs to be provided by external tools. See -# the section "External Indexing and Searching" for details. +# are two flavors of web server based searching depending on the EXTERNAL_SEARCH +# setting. When disabled, doxygen will generate a PHP script for searching and +# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing +# and searching needs to be provided by external tools. See the section +# "External Indexing and Searching" for details. # The default value is: NO. # This tag requires that the tag SEARCHENGINE is set to YES. @@ -1537,7 +1610,7 @@ SERVER_BASED_SEARCH = NO # external search engine pointed to by the SEARCHENGINE_URL option to obtain the # search results. # -# Doxygen ships with an example indexer ( doxyindexer) and search engine +# Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library # Xapian (see: http://xapian.org/). # @@ -1550,13 +1623,13 @@ EXTERNAL_SEARCH = NO # The SEARCHENGINE_URL should point to a search engine hosted by a web server # which will return the search results when EXTERNAL_SEARCH is enabled. # -# Doxygen ships with an example indexer ( doxyindexer) and search engine +# Doxygen ships with an example indexer (doxyindexer) and search engine # (doxysearch.cgi) which are based on the open source search engine library # Xapian (see: http://xapian.org/). See the section "External Indexing and # Searching" for details. # This tag requires that the tag SEARCHENGINE is set to YES. -SEARCHENGINE_URL = +SEARCHENGINE_URL = # When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed # search data is written to a file for indexing by an external tool. With the @@ -1572,7 +1645,7 @@ SEARCHDATA_FILE = searchdata.xml # projects and redirect the results back to the right project. # This tag requires that the tag SEARCHENGINE is set to YES. -EXTERNAL_SEARCH_ID = +EXTERNAL_SEARCH_ID = # The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen # projects other than the one defined by this configuration file, but that are @@ -1582,13 +1655,13 @@ EXTERNAL_SEARCH_ID = # EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ... # This tag requires that the tag SEARCHENGINE is set to YES. -EXTRA_SEARCH_MAPPINGS = +EXTRA_SEARCH_MAPPINGS = #--------------------------------------------------------------------------- # Configuration options related to the LaTeX output #--------------------------------------------------------------------------- -# If the GENERATE_LATEX tag is set to YES doxygen will generate LaTeX output. +# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output. # The default value is: YES. GENERATE_LATEX = NO @@ -1619,7 +1692,7 @@ LATEX_CMD_NAME = latex MAKEINDEX_CMD_NAME = makeindex -# If the COMPACT_LATEX tag is set to YES doxygen generates more compact LaTeX +# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX # documents. This may be useful for small projects and may help to save some # trees in general. # The default value is: NO. @@ -1637,13 +1710,16 @@ COMPACT_LATEX = NO PAPER_TYPE = a4 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names -# that should be included in the LaTeX output. To get the times font for -# instance you can specify -# EXTRA_PACKAGES=times +# that should be included in the LaTeX output. The package can be specified just +# by its name or with the correct syntax as to be used with the LaTeX +# \usepackage command. To get the times font for instance you can specify : +# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times} +# To use the option intlimits with the amsmath package you can specify: +# EXTRA_PACKAGES=[intlimits]{amsmath} # If left blank no extra packages will be included. # This tag requires that the tag GENERATE_LATEX is set to YES. -EXTRA_PACKAGES = +EXTRA_PACKAGES = # The LATEX_HEADER tag can be used to specify a personal LaTeX header for the # generated LaTeX document. The header should contain everything until the first @@ -1653,22 +1729,35 @@ EXTRA_PACKAGES = # # Note: Only use a user-defined header if you know what you are doing! The # following commands have a special meaning inside the header: $title, -# $datetime, $date, $doxygenversion, $projectname, $projectnumber. Doxygen will -# replace them by respectively the title of the page, the current date and time, -# only the current date, the version number of doxygen, the project name (see -# PROJECT_NAME), or the project number (see PROJECT_NUMBER). +# $datetime, $date, $doxygenversion, $projectname, $projectnumber, +# $projectbrief, $projectlogo. Doxygen will replace $title with the empty +# string, for the replacement values of the other commands the user is referred +# to HTML_HEADER. # This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_HEADER = +LATEX_HEADER = # The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the # generated LaTeX document. The footer should contain everything after the last -# chapter. If it is left blank doxygen will generate a standard footer. +# chapter. If it is left blank doxygen will generate a standard footer. See +# LATEX_HEADER for more information on how to generate a default footer and what +# special commands can be used inside the footer. # # Note: Only use a user-defined footer if you know what you are doing! # This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_FOOTER = +LATEX_FOOTER = + +# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# LaTeX style sheets that are included after the standard style sheets created +# by doxygen. Using this option one can overrule certain style aspects. Doxygen +# will copy the style sheet files to the output directory. +# Note: The order of the extra style sheet files is of importance (e.g. the last +# style sheet in the list overrules the setting of the previous ones in the +# list). +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_EXTRA_STYLESHEET = # The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the LATEX_OUTPUT output @@ -1676,7 +1765,7 @@ LATEX_FOOTER = # markers available. # This tag requires that the tag GENERATE_LATEX is set to YES. -LATEX_EXTRA_FILES = +LATEX_EXTRA_FILES = # If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is # prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will @@ -1687,8 +1776,8 @@ LATEX_EXTRA_FILES = PDF_HYPERLINKS = YES -# If the LATEX_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate -# the PDF file directly from the LaTeX files. Set this option to YES to get a +# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate +# the PDF file directly from the LaTeX files. Set this option to YES, to get a # higher quality PDF documentation. # The default value is: YES. # This tag requires that the tag GENERATE_LATEX is set to YES. @@ -1729,11 +1818,19 @@ LATEX_SOURCE_CODE = NO LATEX_BIB_STYLE = plain +# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: NO. +# This tag requires that the tag GENERATE_LATEX is set to YES. + +LATEX_TIMESTAMP = NO + #--------------------------------------------------------------------------- # Configuration options related to the RTF output #--------------------------------------------------------------------------- -# If the GENERATE_RTF tag is set to YES doxygen will generate RTF output. The +# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The # RTF output is optimized for Word 97 and may not look too pretty with other RTF # readers/editors. # The default value is: NO. @@ -1748,7 +1845,7 @@ GENERATE_RTF = NO RTF_OUTPUT = rtf -# If the COMPACT_RTF tag is set to YES doxygen generates more compact RTF +# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF # documents. This may be useful for small projects and may help to save some # trees in general. # The default value is: NO. @@ -1776,20 +1873,30 @@ RTF_HYPERLINKS = NO # default style sheet that doxygen normally uses. # This tag requires that the tag GENERATE_RTF is set to YES. -RTF_STYLESHEET_FILE = +RTF_STYLESHEET_FILE = # Set optional variables used in the generation of an RTF document. Syntax is # similar to doxygen's config file. A template extensions file can be generated # using doxygen -e rtf extensionFile. # This tag requires that the tag GENERATE_RTF is set to YES. -RTF_EXTENSIONS_FILE = +RTF_EXTENSIONS_FILE = + +# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code +# with syntax highlighting in the RTF output. +# +# Note that which sources are shown also depends on other settings such as +# SOURCE_BROWSER. +# The default value is: NO. +# This tag requires that the tag GENERATE_RTF is set to YES. + +RTF_SOURCE_CODE = NO #--------------------------------------------------------------------------- # Configuration options related to the man page output #--------------------------------------------------------------------------- -# If the GENERATE_MAN tag is set to YES doxygen will generate man pages for +# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for # classes and files. # The default value is: NO. @@ -1813,6 +1920,13 @@ MAN_OUTPUT = man MAN_EXTENSION = .3 +# The MAN_SUBDIR tag determines the name of the directory created within +# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by +# MAN_EXTENSION with the initial . removed. +# This tag requires that the tag GENERATE_MAN is set to YES. + +MAN_SUBDIR = + # If the MAN_LINKS tag is set to YES and doxygen generates man output, then it # will generate one additional man file for each entity documented in the real # man page(s). These additional files only source the real man page, but without @@ -1826,7 +1940,7 @@ MAN_LINKS = NO # Configuration options related to the XML output #--------------------------------------------------------------------------- -# If the GENERATE_XML tag is set to YES doxygen will generate an XML file that +# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that # captures the structure of the code including all documentation. # The default value is: NO. @@ -1840,19 +1954,7 @@ GENERATE_XML = NO XML_OUTPUT = xml -# The XML_SCHEMA tag can be used to specify a XML schema, which can be used by a -# validating XML parser to check the syntax of the XML files. -# This tag requires that the tag GENERATE_XML is set to YES. - -XML_SCHEMA = - -# The XML_DTD tag can be used to specify a XML DTD, which can be used by a -# validating XML parser to check the syntax of the XML files. -# This tag requires that the tag GENERATE_XML is set to YES. - -XML_DTD = - -# If the XML_PROGRAMLISTING tag is set to YES doxygen will dump the program +# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program # listings (including syntax highlighting and cross-referencing information) to # the XML output. Note that enabling this will significantly increase the size # of the XML output. @@ -1865,7 +1967,7 @@ XML_PROGRAMLISTING = YES # Configuration options related to the DOCBOOK output #--------------------------------------------------------------------------- -# If the GENERATE_DOCBOOK tag is set to YES doxygen will generate Docbook files +# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files # that can be used to generate PDF. # The default value is: NO. @@ -1879,14 +1981,23 @@ GENERATE_DOCBOOK = NO DOCBOOK_OUTPUT = docbook +# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the +# program listings (including syntax highlighting and cross-referencing +# information) to the DOCBOOK output. Note that enabling this will significantly +# increase the size of the DOCBOOK output. +# The default value is: NO. +# This tag requires that the tag GENERATE_DOCBOOK is set to YES. + +DOCBOOK_PROGRAMLISTING = NO + #--------------------------------------------------------------------------- # Configuration options for the AutoGen Definitions output #--------------------------------------------------------------------------- -# If the GENERATE_AUTOGEN_DEF tag is set to YES doxygen will generate an AutoGen -# Definitions (see http://autogen.sf.net) file that captures the structure of -# the code including all documentation. Note that this feature is still -# experimental and incomplete at the moment. +# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an +# AutoGen Definitions (see http://autogen.sf.net) file that captures the +# structure of the code including all documentation. Note that this feature is +# still experimental and incomplete at the moment. # The default value is: NO. GENERATE_AUTOGEN_DEF = NO @@ -1895,7 +2006,7 @@ GENERATE_AUTOGEN_DEF = NO # Configuration options related to the Perl module output #--------------------------------------------------------------------------- -# If the GENERATE_PERLMOD tag is set to YES doxygen will generate a Perl module +# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module # file that captures the structure of the code including all documentation. # # Note that this feature is still experimental and incomplete at the moment. @@ -1903,7 +2014,7 @@ GENERATE_AUTOGEN_DEF = NO GENERATE_PERLMOD = NO -# If the PERLMOD_LATEX tag is set to YES doxygen will generate the necessary +# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary # Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI # output from the Perl module output. # The default value is: NO. @@ -1911,9 +2022,9 @@ GENERATE_PERLMOD = NO PERLMOD_LATEX = NO -# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be nicely +# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely # formatted so it can be parsed by a human reader. This is useful if you want to -# understand what is going on. On the other hand, if this tag is set to NO the +# understand what is going on. On the other hand, if this tag is set to NO, the # size of the Perl module output will be much smaller and Perl will parse it # just the same. # The default value is: YES. @@ -1927,20 +2038,20 @@ PERLMOD_PRETTY = YES # overwrite each other's variables. # This tag requires that the tag GENERATE_PERLMOD is set to YES. -PERLMOD_MAKEVAR_PREFIX = +PERLMOD_MAKEVAR_PREFIX = #--------------------------------------------------------------------------- # Configuration options related to the preprocessor #--------------------------------------------------------------------------- -# If the ENABLE_PREPROCESSING tag is set to YES doxygen will evaluate all +# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all # C-preprocessor directives found in the sources and include files. # The default value is: YES. ENABLE_PREPROCESSING = YES -# If the MACRO_EXPANSION tag is set to YES doxygen will expand all macro names -# in the source code. If set to NO only conditional compilation will be +# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names +# in the source code. If set to NO, only conditional compilation will be # performed. Macro expansion can be done in a controlled way by setting # EXPAND_ONLY_PREDEF to YES. # The default value is: NO. @@ -1956,7 +2067,7 @@ MACRO_EXPANSION = NO EXPAND_ONLY_PREDEF = NO -# If the SEARCH_INCLUDES tag is set to YES the includes files in the +# If the SEARCH_INCLUDES tag is set to YES, the include files in the # INCLUDE_PATH will be searched if a #include is found. # The default value is: YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. @@ -1968,7 +2079,7 @@ SEARCH_INCLUDES = YES # preprocessor. # This tag requires that the tag SEARCH_INCLUDES is set to YES. -INCLUDE_PATH = +INCLUDE_PATH = # You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard # patterns (like *.h and *.hpp) to filter out the header-files in the @@ -1976,7 +2087,7 @@ INCLUDE_PATH = # used. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -INCLUDE_FILE_PATTERNS = +INCLUDE_FILE_PATTERNS = # The PREDEFINED tag can be used to specify one or more macro names that are # defined before the preprocessor is started (similar to the -D option of e.g. @@ -1986,7 +2097,7 @@ INCLUDE_FILE_PATTERNS = # recursively expanded use the := operator instead of the = operator. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -PREDEFINED = +PREDEFINED = # If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this # tag can be used to specify a list of macro names that should be expanded. The @@ -1995,12 +2106,12 @@ PREDEFINED = # definition found in the source code. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. -EXPAND_AS_DEFINED = +EXPAND_AS_DEFINED = # If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will -# remove all refrences to function-like macros that are alone on a line, have an -# all uppercase name, and do not end with a semicolon. Such function macros are -# typically used for boiler-plate code, and will confuse the parser if not +# remove all references to function-like macros that are alone on a line, have +# an all uppercase name, and do not end with a semicolon. Such function macros +# are typically used for boiler-plate code, and will confuse the parser if not # removed. # The default value is: YES. # This tag requires that the tag ENABLE_PREPROCESSING is set to YES. @@ -2020,32 +2131,33 @@ SKIP_FUNCTION_MACROS = YES # where loc1 and loc2 can be relative or absolute paths or URLs. See the # section "Linking to external documentation" for more information about the use # of tag files. -# Note: Each tag file must have an unique name (where the name does NOT include +# Note: Each tag file must have a unique name (where the name does NOT include # the path). If a tag file is not located in the directory in which doxygen is # run, you must also specify the path to the tagfile here. -TAGFILES = +TAGFILES = # When a file name is specified after GENERATE_TAGFILE, doxygen will create a # tag file that is based on the input files it reads. See section "Linking to # external documentation" for more information about the usage of tag files. -GENERATE_TAGFILE = +GENERATE_TAGFILE = -# If the ALLEXTERNALS tag is set to YES all external class will be listed in the -# class index. If set to NO only the inherited external classes will be listed. +# If the ALLEXTERNALS tag is set to YES, all external class will be listed in +# the class index. If set to NO, only the inherited external classes will be +# listed. # The default value is: NO. ALLEXTERNALS = NO -# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed in -# the modules index. If set to NO, only the current project's groups will be +# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed +# in the modules index. If set to NO, only the current project's groups will be # listed. # The default value is: YES. EXTERNAL_GROUPS = YES -# If the EXTERNAL_PAGES tag is set to YES all external pages will be listed in +# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in # the related pages index. If set to NO, only the current project's pages will # be listed. # The default value is: YES. @@ -2062,7 +2174,7 @@ PERL_PATH = /usr/bin/perl # Configuration options related to the dot tool #--------------------------------------------------------------------------- -# If the CLASS_DIAGRAMS tag is set to YES doxygen will generate a class diagram +# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram # (in HTML and LaTeX) for classes with base or super classes. Setting the tag to # NO turns the diagrams off. Note that this option also works with HAVE_DOT # disabled, but it is recommended to install and use dot, since it yields more @@ -2078,16 +2190,16 @@ CLASS_DIAGRAMS = YES # the mscgen tool resides. If left empty the tool is assumed to be found in the # default search path. -MSCGEN_PATH = +MSCGEN_PATH = # You can include diagrams made with dia in doxygen documentation. Doxygen will # then run dia to produce the diagram and insert it in the documentation. The # DIA_PATH tag allows you to specify the directory where the dia binary resides. # If left empty dia is assumed to be found in the default search path. -DIA_PATH = +DIA_PATH = -# If set to YES, the inheritance and collaboration graphs will hide inheritance +# If set to YES the inheritance and collaboration graphs will hide inheritance # and usage relations if the target is undocumented or is not a class. # The default value is: YES. @@ -2098,7 +2210,7 @@ HIDE_UNDOC_RELATIONS = YES # http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent # Bell Labs. The other options in this section have no effect if this option is # set to NO -# The default value is: NO. +# The default value is: YES. HAVE_DOT = NO @@ -2112,7 +2224,7 @@ HAVE_DOT = NO DOT_NUM_THREADS = 0 -# When you want a differently looking font n the dot files that doxygen +# When you want a differently looking font in the dot files that doxygen # generates you can specify the font name using DOT_FONTNAME. You need to make # sure dot is able to find the font, which can be done by putting it in a # standard location or by setting the DOTFONTPATH environment variable or by @@ -2134,7 +2246,7 @@ DOT_FONTSIZE = 10 # the path where dot can find it using this tag. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_FONTPATH = +DOT_FONTPATH = # If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for # each documented class showing the direct and indirect inheritance relations. @@ -2160,7 +2272,7 @@ COLLABORATION_GRAPH = YES GROUP_GRAPHS = YES -# If the UML_LOOK tag is set to YES doxygen will generate inheritance and +# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and # collaboration diagrams in a style similar to the OMG's Unified Modeling # Language. # The default value is: NO. @@ -2212,7 +2324,8 @@ INCLUDED_BY_GRAPH = YES # # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable call graphs for selected -# functions only using the \callgraph command. +# functions only using the \callgraph command. Disabling a call graph can be +# accomplished by means of the command \hidecallgraph. # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2223,7 +2336,8 @@ CALL_GRAPH = NO # # Note that enabling this option will significantly increase the time of a run. # So in most cases it will be better to enable caller graphs for selected -# functions only using the \callergraph command. +# functions only using the \callergraph command. Disabling a caller graph can be +# accomplished by means of the command \hidecallergraph. # The default value is: NO. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2246,11 +2360,17 @@ GRAPHICAL_HIERARCHY = YES DIRECTORY_GRAPH = YES # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images -# generated by dot. +# generated by dot. For an explanation of the image formats see the section +# output formats in the documentation of the dot tool (Graphviz (see: +# http://www.graphviz.org/)). # Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order # to make the SVG files visible in IE 9+ (other browsers do not have this # requirement). -# Possible values are: png, jpg, gif and svg. +# Possible values are: png, png:cairo, png:cairo:cairo, png:cairo:gd, png:gd, +# png:gd:gd, jpg, jpg:cairo, jpg:cairo:gd, jpg:gd, jpg:gd:gd, gif, gif:cairo, +# gif:cairo:gd, gif:gd, gif:gd:gd, svg, png:gd, png:gd:gd, png:cairo, +# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and +# png:gdiplus:gdiplus. # The default value is: png. # This tag requires that the tag HAVE_DOT is set to YES. @@ -2272,26 +2392,44 @@ INTERACTIVE_SVG = NO # found. If left blank, it is assumed the dot tool can be found in the path. # This tag requires that the tag HAVE_DOT is set to YES. -DOT_PATH = +DOT_PATH = # The DOTFILE_DIRS tag can be used to specify one or more directories that # contain dot files that are included in the documentation (see the \dotfile # command). # This tag requires that the tag HAVE_DOT is set to YES. -DOTFILE_DIRS = +DOTFILE_DIRS = # The MSCFILE_DIRS tag can be used to specify one or more directories that # contain msc files that are included in the documentation (see the \mscfile # command). -MSCFILE_DIRS = +MSCFILE_DIRS = # The DIAFILE_DIRS tag can be used to specify one or more directories that # contain dia files that are included in the documentation (see the \diafile # command). -DIAFILE_DIRS = +DIAFILE_DIRS = + +# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the +# path where java can find the plantuml.jar file. If left blank, it is assumed +# PlantUML is not used or called during a preprocessing step. Doxygen will +# generate a warning when it encounters a \startuml command in this case and +# will not generate output for the diagram. + +PLANTUML_JAR_PATH = + +# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a +# configuration file for plantuml. + +PLANTUML_CFG_FILE = + +# When using plantuml, the specified paths are searched for files specified by +# the !include statement in a plantuml block. + +PLANTUML_INCLUDE_PATH = # The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes # that will be shown in the graph. If the number of nodes in a graph becomes @@ -2329,7 +2467,7 @@ MAX_DOT_GRAPH_DEPTH = 0 DOT_TRANSPARENT = NO -# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output +# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output # files in one run (i.e. multiple -o and -T options on the command line). This # makes dot run faster, but since only newer versions of dot (>1.8.10) support # this, this feature is disabled by default. @@ -2346,7 +2484,7 @@ DOT_MULTI_TARGETS = NO GENERATE_LEGEND = YES -# If the DOT_CLEANUP tag is set to YES doxygen will remove the intermediate dot +# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot # files that are used to generate the various graphs. # The default value is: YES. # This tag requires that the tag HAVE_DOT is set to YES. From 1d1458d2278cf3741e4fe39b94beb309c16ad1b6 Mon Sep 17 00:00:00 2001 From: Lionel AINS Date: Thu, 21 Nov 2019 16:12:58 +0100 Subject: [PATCH 31/44] Fixing doxygen comments for all spi/ subfolders --- src/spi/ILogger.h | 52 ++++++++++++++++++++++++++---- src/spi/console/ConsoleLogger.h | 3 ++ src/spi/mock-uart/MockUartDriver.h | 4 +-- src/spi/raritan/RaritanEventLoop.h | 9 ++++++ src/spi/raritan/RaritanLogger.h | 21 +++++------- src/tests/gp_tests.cpp | 3 ++ 6 files changed, 71 insertions(+), 21 deletions(-) diff --git a/src/spi/ILogger.h b/src/spi/ILogger.h index 75a25293..02c73ab4 100644 --- a/src/spi/ILogger.h +++ b/src/spi/ILogger.h @@ -7,7 +7,9 @@ */ /** - * @brief The define below is to allow for seamless integration of the SPI, calls to logger will be as easy as invoking plog() + * @defgroup printf_compat_logger_macros printf-style logging functions + * + * The define below is to allow for seamless integration of the SPI, calls to logger will be as easy as invoking plog() * * plog() takes at least two arguments: the first one is the log level, the second is the format (following printf convention), followed by as many argument as required by the format string * plogE() is a shortcut for the error logging, thus @@ -18,16 +20,36 @@ * @code * plog(LOG_LEVEL::ERROR, "Hello %!", "World"); * @endcode + * + * @{ + */ + +/** + * @brief Generic logger getter (uses debug level) + */ +#define plog SINGLETON_LOGGER_CLASS_NAME::getInstance().debugLogger.log +/** + * @brief Error logger getter */ -#define plog SINGLETON_LOGGER_CLASS_NAME::getInstance().outputGenericLog #define plogE SINGLETON_LOGGER_CLASS_NAME::getInstance().errorLogger.log +/** + * @brief Warning logger getter + */ #define plogW SINGLETON_LOGGER_CLASS_NAME::getInstance().warningLogger.log +/** + * @brief Info logger getter + */ #define plogI SINGLETON_LOGGER_CLASS_NAME::getInstance().infoLogger.log +/** + * @brief Debug logger getter + */ #define plogD SINGLETON_LOGGER_CLASS_NAME::getInstance().debugLogger.log -#define plogT SINGLETON_LOGGER_CLASS_NAME::getInstance().traceLogger.log +/** @} */ /** - * @brief The defines below allow to log directly through an ostream + * @defgroup ostream_compat_logger_macros ostream-style logging functions + * + * The defines below allow to log directly through an ostream * * clog is a default logger stream * clogE is the error logger stream @@ -39,12 +61,32 @@ * @code * plogE("Error"); * @endcode + * + * @{ + */ + +/** + * @brief Generic logger getter (uses debug level) */ #define clog ILogger::loggerDebugStream +/** + * @brief Error logger getter + */ #define clogE ILogger::loggerErrorStream +/** + * @brief Warning logger getter + */ #define clogW ILogger::loggerWarningStream +/** + * @brief Info logger getter + */ #define clogI ILogger::loggerInfoStream +/** + * @brief Debug logger getter + */ #define clogD ILogger::loggerDebugStream +/** @} */ + /* Note: we are not using pragma once here because we want the defines above to be applied even if include is done multiple times * The code below, however, will be include once, so it is "manually" protected from multiple includes using an #ifdef directive @@ -136,8 +178,6 @@ class ILoggerStream : public std::streambuf { /** * @brief Unmute this logger output (logs may still not be output depending on the max log level has been setup) - * - * @param enabled Should this logger be enabled? */ virtual void unmute() { this->muted = false; diff --git a/src/spi/console/ConsoleLogger.h b/src/spi/console/ConsoleLogger.h index 131da596..28c575c0 100644 --- a/src/spi/console/ConsoleLogger.h +++ b/src/spi/console/ConsoleLogger.h @@ -6,6 +6,9 @@ #pragma once +/** + * @brief Macro to allow logger getter to fetch the singleton instance of this logger class +**/ #define SINGLETON_LOGGER_CLASS_NAME ConsoleLogger #include "../ILogger.h" diff --git a/src/spi/mock-uart/MockUartDriver.h b/src/spi/mock-uart/MockUartDriver.h index 47744024..68cc2824 100644 --- a/src/spi/mock-uart/MockUartDriver.h +++ b/src/spi/mock-uart/MockUartDriver.h @@ -144,7 +144,7 @@ class MockUartDriver : public IUartDriver { /** * @brief Get the number of bytes read from the emulated serial port so far (cumulative) * - * @param The total number of bytes delivered so far by the emulated serial port + * @return The total number of bytes delivered so far by the emulated serial port */ size_t getDeliveredIncomingBytesCount(); @@ -165,7 +165,7 @@ class MockUartDriver : public IUartDriver { std::mutex scheduledReadQueueMutex; /*!< A mutex to handle access to scheduledReadQueue, scheduledReadBytesCount or deliveredReadBytesCount */ std::queue scheduledReadQueue; /*!< The scheduled read bytes queue. Grab scheduledReadQueueMutex before accessing this */ public: - std::recursive_mutex writeMutex; /* Mutex to protect writes... recursive to allow the caller to grab the mutex for us */ + std::recursive_mutex writeMutex; /*!< Mutex to protect writes... recursive to allow the caller to grab the mutex for us */ private: GenericAsyncDataInputObservable *dataInputObservable; /*!< The observable that will notify observers when new bytes are available on the UART */ std::function delta)> onWriteCallback; /*!< Callback invoked each time bytes are written to the emulated UART, this callback must have a prototype that takes 3 parameters: size_t& writtenCnt, const void* buf, size_t cnt, std::chrono::duration delta. delta being the time since last bytes were written (in ms) */ diff --git a/src/spi/raritan/RaritanEventLoop.h b/src/spi/raritan/RaritanEventLoop.h index 62236d7a..ae857868 100644 --- a/src/spi/raritan/RaritanEventLoop.h +++ b/src/spi/raritan/RaritanEventLoop.h @@ -20,9 +20,18 @@ class RaritanEventLoop { public: /** * @brief Default constructor + * + * Will use the singleton selector */ RaritanEventLoop(); + + /** + * @brief Constructor using a pre-existing selector + * + * @param selector The selector to use for the mainloop + */ RaritanEventLoop(pp::Selector &selector); + /** * @brief Run the main loop */ diff --git a/src/spi/raritan/RaritanLogger.h b/src/spi/raritan/RaritanLogger.h index dce7fe74..6c4af75e 100644 --- a/src/spi/raritan/RaritanLogger.h +++ b/src/spi/raritan/RaritanLogger.h @@ -6,6 +6,9 @@ #pragma once +/** + * @brief Macro to allow logger getter to fetch the singleton instance of this logger class +**/ #define SINGLETON_LOGGER_CLASS_NAME RaritanLogger #include "../ILogger.h" #include @@ -60,9 +63,7 @@ class RaritanGenericLogger : public ILoggerStream { class RaritanErrorLogger : public RaritanGenericLogger { public: /** - * @brief Constructor - * - * @param logLevel The log level handled by this logger instance. This is fixed at construction and cannot be changed afterwards + * @brief Default constructor */ RaritanErrorLogger() : RaritanGenericLogger(LOG_LEVEL::ERROR) { @@ -103,9 +104,7 @@ class RaritanErrorLogger : public RaritanGenericLogger { class RaritanWarningLogger : public RaritanGenericLogger { public: /** - * @brief Constructor - * - * @param logLevel The log level handled by this logger instance. This is fixed at construction and cannot be changed afterwards + * @brief Default constructor */ RaritanWarningLogger() : RaritanGenericLogger(LOG_LEVEL::WARNING) { @@ -146,9 +145,7 @@ class RaritanWarningLogger : public RaritanGenericLogger { class RaritanInfoLogger : public RaritanGenericLogger { public: /** - * @brief Constructor - * - * @param logLevel The log level handled by this logger instance. This is fixed at construction and cannot be changed afterwards + * @brief Default constructor */ RaritanInfoLogger() : RaritanGenericLogger(LOG_LEVEL::INFO) { @@ -189,9 +186,7 @@ class RaritanInfoLogger : public RaritanGenericLogger { class RaritanDebugLogger : public RaritanGenericLogger { public: /** - * @brief Constructor - * - * @param logLevel The log level handled by this logger instance. This is fixed at construction and cannot be changed afterwards + * @brief Default constructor */ RaritanDebugLogger() : RaritanGenericLogger(LOG_LEVEL::DEBUG) { @@ -232,7 +227,7 @@ class RaritanDebugLogger : public RaritanGenericLogger { class RaritanLogger : public ILogger { private: /** - * @brief Default constructor + * @brief Constructor * * @param errorLogger The logger to use for error messages * @param warningLogger The logger to use for warning messages diff --git a/src/tests/gp_tests.cpp b/src/tests/gp_tests.cpp index 7add326c..11be56e5 100644 --- a/src/tests/gp_tests.cpp +++ b/src/tests/gp_tests.cpp @@ -10,6 +10,9 @@ #include "../spi/GenericLogger.h" #include "../example/CAppDemo.h" +/** + * @brief Class implementing an observer that validates state transition during a sample ezsp in/out test sequence +**/ class GPRecvSensorMeasurementTest : public IAsyncDataInputObserver { public: /** From 48f9dcfd5d82a135a2bd8e0c90388c8d4e569e2f Mon Sep 17 00:00:00 2001 From: Lionel AINS Date: Thu, 21 Nov 2019 16:14:28 +0100 Subject: [PATCH 32/44] Fixing @file doxygen tag --- src/domain/zbmessage/apsoption.cpp | 2 +- src/domain/zbmessage/apsoption.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/domain/zbmessage/apsoption.cpp b/src/domain/zbmessage/apsoption.cpp index a2ffdd7e..769861cd 100644 --- a/src/domain/zbmessage/apsoption.cpp +++ b/src/domain/zbmessage/apsoption.cpp @@ -1,5 +1,5 @@ /** - * @file apsoptions.h + * @file apsoption.cpp * * @brief Handles encoding/decoding of the 16-bit APS option word */ diff --git a/src/domain/zbmessage/apsoption.h b/src/domain/zbmessage/apsoption.h index 0cecd0ea..167c6aac 100644 --- a/src/domain/zbmessage/apsoption.h +++ b/src/domain/zbmessage/apsoption.h @@ -1,5 +1,5 @@ /** - * @file apsoptions.h + * @file apsoption.h * * @brief Handles encoding/decoding of the 16-bit APS option word */ From d8d27e3f75dbc412859217201c7b5bcca98ed4aa Mon Sep 17 00:00:00 2001 From: Lionel AINS Date: Thu, 21 Nov 2019 17:06:02 +0100 Subject: [PATCH 33/44] Adding class CGpDevice to encapsulate a GP source ID+its key --- src/Makefile | 1 + src/example/CAppDemo.cpp | 8 ++++---- src/example/CAppDemo.h | 3 ++- src/example/mainEzspTest.cpp | 8 ++++---- src/libezsp.mk.inc | 1 + 5 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/Makefile b/src/Makefile index 26ea08cc..4dad4fb3 100644 --- a/src/Makefile +++ b/src/Makefile @@ -15,6 +15,7 @@ libezsp_SRCS = domain/zbmessage/zigbee-message.cpp \ domain/zbmessage/apsoption.cpp \ domain/zbmessage/aps.cpp \ domain/zbmessage/zdp-enum.cpp \ + domain/zbmessage/green-power-device.cpp \ domain/zbmessage/green-power-frame.cpp \ domain/zigbee-tools/green-power-sink.cpp \ domain/zbmessage/green-power-sink-table-entry.cpp \ diff --git a/src/example/CAppDemo.cpp b/src/example/CAppDemo.cpp index 7e64b6a8..6c5fa8a4 100644 --- a/src/example/CAppDemo.cpp +++ b/src/example/CAppDemo.cpp @@ -23,7 +23,7 @@ CAppDemo::CAppDemo(IUartDriver& uartDriver, bool openGpCommissionning, bool openZigbeeCommissionning, unsigned int networkChannel, - const std::vector& sourceIdList) : + const std::vector& gpDevList) : dongle(i_timer_factory, this), zb_messaging(dongle, i_timer_factory), zb_nwk(dongle, zb_messaging), @@ -46,9 +46,9 @@ CAppDemo::CAppDemo(IUartDriver& uartDriver, clogI << "CAppDemo open success !" << std::endl; dongle.registerObserver(this); gp_sink.registerObserver(this); - for (auto i : sourceIdList) { - clogD << "Watching source ID 0x" << std::hex << std::setw(8) << std::setfill('0') << i << "\n"; - gp_sink.registerGpd(i); + for (auto i : gpDevList) { + clogD << "Watching source ID 0x" << std::hex << std::setw(8) << std::setfill('0') << i.getSourceId() << "\n"; + gp_sink.registerGpd(i.getSourceId()); } setAppState(APP_INIT_IN_PROGRESS); } diff --git a/src/example/CAppDemo.h b/src/example/CAppDemo.h index 068c0573..f2ff8b19 100644 --- a/src/example/CAppDemo.h +++ b/src/example/CAppDemo.h @@ -10,6 +10,7 @@ #include "../domain/zigbee-tools/zigbee-networking.h" #include "../domain/zigbee-tools/zigbee-messaging.h" #include "../domain/zigbee-tools/green-power-sink.h" +#include "../domain/zbmessage/green-power-device.h" #include "../spi/IUartDriver.h" #include "../spi/ITimerFactory.h" #include "../spi/ILogger.h" @@ -28,7 +29,7 @@ typedef enum class CAppDemo : public CEzspDongleObserver, CGpObserver { public: - CAppDemo(IUartDriver& uartDriver, ITimerFactory &i_timer_factory, bool reset=false, bool openGpCommissionning=false, bool openZigbeeCommissionning=false, unsigned int networkChannel=11, const std::vector& sourceIdList={}); + CAppDemo(IUartDriver& uartDriver, ITimerFactory &i_timer_factory, bool reset=false, bool openGpCommissionning=false, bool openZigbeeCommissionning=false, unsigned int networkChannel=11, const std::vector& gpDevList={}); /** * Callback diff --git a/src/example/mainEzspTest.cpp b/src/example/mainEzspTest.cpp index f2d48a89..43ed2740 100644 --- a/src/example/mainEzspTest.cpp +++ b/src/example/mainEzspTest.cpp @@ -56,7 +56,7 @@ int main(int argc, char **argv) { int optionIndex=0; int c; bool debugEnabled = false; - std::vector sourceIdList; + std::vector gpDevDataList; unsigned int resetToChannel = 0; std::string serialPort("/dev/ttyUSB0"); bool openGpCommissionningAtStartup = false; @@ -80,8 +80,8 @@ int main(int argc, char **argv) { sourceId << std::hex << optarg; unsigned int sourceIdValue; sourceId >> sourceIdValue; - if (sourceIdValue(-1)) { /* Protection against overflow */ - sourceIdList.push_back(sourceIdValue); + if (sourceIdValue(-1)) { /* Protection against overflow */ + gpDevDataList.push_back(CGpDevice(sourceIdValue, CGpDevice::UNKNOWN_KEY)); } else { clogE << "Invalid source ID: " << optarg << "\n"; @@ -126,7 +126,7 @@ int main(int argc, char **argv) { return 1; } - CAppDemo app(uartDriver, timerFactory, (resetToChannel!=0), openGpCommissionningAtStartup, openZigbeeNetworkAtStartup, resetToChannel, sourceIdList); /* If a channel was provided, reset the network and recreate it on the provided channel */ + CAppDemo app(uartDriver, timerFactory, (resetToChannel!=0), openGpCommissionningAtStartup, openZigbeeNetworkAtStartup, resetToChannel, gpDevDataList); /* If a channel was provided, reset the network and recreate it on the provided channel */ #ifdef USE_SERIALCPP std::string line; diff --git a/src/libezsp.mk.inc b/src/libezsp.mk.inc index f82f9a09..3d1d31ba 100644 --- a/src/libezsp.mk.inc +++ b/src/libezsp.mk.inc @@ -3,6 +3,7 @@ LIBEZSP_COMMON_SRC = \ $(SRC_DOMAIN_PATH)/ash.cpp \ $(SRC_DOMAIN_PATH)/custom-aes.cpp \ $(SRC_DOMAIN_PATH)/zbmessage/green-power-frame.cpp \ + $(SRC_DOMAIN_PATH)/zbmessage/green-power-device.cpp \ $(SRC_DOMAIN_PATH)/zbmessage/green-power-sink-table-entry.cpp \ $(SRC_DOMAIN_PATH)/zbmessage/gpd-commissioning-command-payload.cpp \ $(SRC_DOMAIN_PATH)/zbmessage/gp-pairing-command-option-struct.cpp \ From cf51bb0cd34bc221fb3da5660898e013d1a62b26 Mon Sep 17 00:00:00 2001 From: Lionel AINS Date: Thu, 21 Nov 2019 17:19:41 +0100 Subject: [PATCH 34/44] Using CGpDevice class defined in 4b7697dec9092f3a1671d1e809fd11b536b873a2 --- src/domain/zigbee-tools/green-power-sink.cpp | 10 +++++----- src/domain/zigbee-tools/green-power-sink.h | 7 +++++-- src/example/CAppDemo.cpp | 2 +- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/domain/zigbee-tools/green-power-sink.cpp b/src/domain/zigbee-tools/green-power-sink.cpp index 8e1d42cc..52c2b822 100644 --- a/src/domain/zigbee-tools/green-power-sink.cpp +++ b/src/domain/zigbee-tools/green-power-sink.cpp @@ -116,15 +116,15 @@ uint8_t CGpSink::registerGpd( uint32_t i_source_id ) return sink_table.addEntry(l_entry); } -void CGpSink::registerGpd( uint32_t i_source_id, std::vector i_key ) +void CGpSink::registerGpd( const CGpDevice &gpd ) { // save offline information - CEmberGpAddressStruct l_gp_addr(i_source_id); + CEmberGpAddressStruct l_gp_addr(gpd.getSourceId()); sink_table_entry.setGpdAddress(l_gp_addr); - sink_table_entry.setKey(i_key); + sink_table_entry.setKey(gpd.getKey()); // request sink table entry - gpSinkTableFindOrAllocateEntry( i_source_id ); + gpSinkTableFindOrAllocateEntry( gpd.getSourceId() ); // set state setSinkState(SINK_COM_OFFLINE_IN_PROGRESS); @@ -628,4 +628,4 @@ void CGpSink::setSinkState( ESinkState i_state ) auto it = MyEnumStrings.find(sink_state); /* FIXME: we issue a warning, but the variable app_state is now out of bounds */ std::string error_str = it == MyEnumStrings.end() ? "OUT_OF_RANGE" : it->second; clogI << "SINK State change : " << error_str << std::endl; -} \ No newline at end of file +} diff --git a/src/domain/zigbee-tools/green-power-sink.h b/src/domain/zigbee-tools/green-power-sink.h index 4e23ea0f..4299045d 100644 --- a/src/domain/zigbee-tools/green-power-sink.h +++ b/src/domain/zigbee-tools/green-power-sink.h @@ -7,6 +7,7 @@ #pragma once #include "../zbmessage/green-power-frame.h" +#include "../zbmessage/green-power-device.h" #include "../green-power-observer.h" #include "../ezsp-dongle.h" #include "zigbee-messaging.h" @@ -67,9 +68,11 @@ class CGpSink : public CEzspDongleObserver uint8_t registerGpd( uint32_t i_source_id ); /** - * @brief add a green power device + * @brief Add a green power device to this sink + * + * @param gpd The description oof the device to add */ - void registerGpd( uint32_t i_source_id, std::vector i_key ); + void registerGpd( const CGpDevice &gpd ); /** * Observer diff --git a/src/example/CAppDemo.cpp b/src/example/CAppDemo.cpp index 6c5fa8a4..665c1803 100644 --- a/src/example/CAppDemo.cpp +++ b/src/example/CAppDemo.cpp @@ -283,7 +283,7 @@ void CAppDemo::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_r else { // debug : add hardcoded gpd - gp_sink.registerGpd(0x00510050,{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F}); + gp_sink.registerGpd(CGpDevice(0x00510050,{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F})); } From ed66e956c6bfd4841bd3733a6bb8b1e96f10e0f7 Mon Sep 17 00:00:00 2001 From: Lionel AINS Date: Fri, 22 Nov 2019 09:13:14 +0100 Subject: [PATCH 35/44] Adding command-line parsing for GPD source id+key --- src/example/CAppDemo.cpp | 13 +++++----- src/example/CAppDemo.h | 1 + src/example/mainEzspTest.cpp | 46 +++++++++++++++++++++++++++--------- 3 files changed, 43 insertions(+), 17 deletions(-) diff --git a/src/example/CAppDemo.cpp b/src/example/CAppDemo.cpp index 665c1803..78d2a214 100644 --- a/src/example/CAppDemo.cpp +++ b/src/example/CAppDemo.cpp @@ -34,7 +34,8 @@ CAppDemo::CAppDemo(IUartDriver& uartDriver, reset_wanted(reset), openGpCommissionningAtStartup(openGpCommissionning), openZigbeeCommissionningAtStartup(openZigbeeCommissionning), - channel(networkChannel) + channel(networkChannel), + gpDevList(gpDevList) { setAppState(APP_NOT_INIT); // uart @@ -46,10 +47,6 @@ CAppDemo::CAppDemo(IUartDriver& uartDriver, clogI << "CAppDemo open success !" << std::endl; dongle.registerObserver(this); gp_sink.registerObserver(this); - for (auto i : gpDevList) { - clogD << "Watching source ID 0x" << std::hex << std::setw(8) << std::setfill('0') << i.getSourceId() << "\n"; - gp_sink.registerGpd(i.getSourceId()); - } setAppState(APP_INIT_IN_PROGRESS); } // save parameter @@ -282,8 +279,12 @@ void CAppDemo::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_r } else { + for (auto i : this->gpDevList) { + clogD << "Adding source ID 0x" << std::hex << std::setw(8) << std::setfill('0') << i.getSourceId() << " to monitored devices\n"; + gp_sink.registerGpd(i); + } // debug : add hardcoded gpd - gp_sink.registerGpd(CGpDevice(0x00510050,{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F})); + //gp_sink.registerGpd(CGpDevice(0x00510050,{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F})); } diff --git a/src/example/CAppDemo.h b/src/example/CAppDemo.h index f2ff8b19..93f9c9c8 100644 --- a/src/example/CAppDemo.h +++ b/src/example/CAppDemo.h @@ -59,5 +59,6 @@ class CAppDemo : public CEzspDongleObserver, CGpObserver bool openGpCommissionningAtStartup; /* Do we open GP commissionning at dongle initialization? */ bool openZigbeeCommissionningAtStartup; /* Do we open the Zigbee network at dongle initialization? */ unsigned int channel; /*!< The Zigbee channel on which to create the network (if reset_wanted is set) */ + std::vector gpDevList; /*!< The list of GP devices we are monitoring */ }; diff --git a/src/example/mainEzspTest.cpp b/src/example/mainEzspTest.cpp index 43ed2740..3a862ecc 100644 --- a/src/example/mainEzspTest.cpp +++ b/src/example/mainEzspTest.cpp @@ -25,6 +25,7 @@ #include #include #include +//#include // For debug static void writeUsage(const char* progname, FILE *f) { fprintf(f,"\n"); @@ -37,7 +38,7 @@ static void writeUsage(const char* progname, FILE *f) { fprintf(f,"-G (--open-gp-commissionning) : open the Green Power commissionning session at startup\n"); fprintf(f,"-u (--serial-port) : use a specific serial port (default: '/dev/ttyUSB0')\n"); fprintf(f,"-r (--reset-to-channel) : force re-creation of a network on the specified channel (discards previously existing network)\n"); - fprintf(f,"-s (--source-id) : enables receiving from a device with this source-id, formatted as a 8-digit hexadecimal string (eg: 'ffae1245') (repeated -s options are allowed)\n"); + fprintf(f,"-s (--source-id) : adds a device to the monitored list, based on its source-id & key, id being formatted as a 8-digit hexadecimal string (eg: 'ffae1245'), and key as a 16-byte/32-digit hex string (repeated -s options are allowed)\n"); } int main(int argc, char **argv) { @@ -76,17 +77,40 @@ int main(int argc, char **argv) { switch (c) { case 's': { - std::stringstream sourceId; - sourceId << std::hex << optarg; - unsigned int sourceIdValue; - sourceId >> sourceIdValue; - if (sourceIdValue(-1)) { /* Protection against overflow */ - gpDevDataList.push_back(CGpDevice(sourceIdValue, CGpDevice::UNKNOWN_KEY)); + std::istringstream gpDevDataStream(optarg); + std::string gpDevSourceIdstr; + if (std::getline(gpDevDataStream, gpDevSourceIdstr, '/')) { + std::stringstream gpDevSourceIdStream; + gpDevSourceIdStream << std::hex << gpDevSourceIdstr; + unsigned int sourceIdValue; + gpDevSourceIdStream >> sourceIdValue; + if (sourceIdValue(-1)) { /* Protection against overflow */ + //std::cerr << "Read source ID part of arg: " << std::hex << std::setw(8) << std::setfill('0') << sourceIdValue << "\n"; + std::string gpDevKeyStr; + gpDevDataStream >> gpDevKeyStr; /* Read everything after the separator, which should be the key */ + //std::cerr << "Read key part of arg: " << gpDevKeyStr << "\n"; + if (gpDevKeyStr.length() != 32) { + clogE << "Invalid key length: " << gpDevKeyStr << " (should be 16-bytes long). Ignoring this entry\n"; + } + else { + EmberKeyData keyValue(CGpDevice::UNKNOWN_KEY); + if (gpDevKeyStr != "") { + std::vector argAsBytes; + for (unsigned int i = 0; i < gpDevKeyStr.length(); i += 2){ + std::string byteString = gpDevKeyStr.substr(i, 2); + argAsBytes.push_back(static_cast(strtol(byteString.c_str(), NULL, 16))); + } + //for (uint8_t loop=0; loop Date: Fri, 22 Nov 2019 09:24:18 +0100 Subject: [PATCH 36/44] Fixing doxygen @file tags --- .../ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp | 2 +- .../ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp | 2 +- .../ezsp-protocol/struct/ember-gp-sink-table-options-field.h | 2 +- src/domain/zbmessage/gpd-commissioning-command-payload.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp index 05145ea2..3823bf71 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp @@ -1,5 +1,5 @@ /** - * @file ember-g-sink-table-entry-struct.cpp + * @file ember-gp-sink-table-entry-struct.cpp * * @brief Represents one sink table entry from Ember */ diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp index 13d51954..8db364e9 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp @@ -1,5 +1,5 @@ /** - * @file ember-gp-sink-table-option-field.cpp + * @file ember-gp-sink-table-options-field.cpp * * @brief Represents Ember's sink table entry options bit field * diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h index cf64af30..7fe9246c 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h @@ -1,5 +1,5 @@ /** - * @file ember-gp-sink-table-option-field.h + * @file ember-gp-sink-table-options-field.h * * @brief Represents Ember's sink table entry options bit field * diff --git a/src/domain/zbmessage/gpd-commissioning-command-payload.h b/src/domain/zbmessage/gpd-commissioning-command-payload.h index e448711d..c2d8c201 100644 --- a/src/domain/zbmessage/gpd-commissioning-command-payload.h +++ b/src/domain/zbmessage/gpd-commissioning-command-payload.h @@ -1,5 +1,5 @@ /** - * @file gpd-commissionning-command-payload.h + * @file gpd-commissioning-command-payload.h * * @brief Decoding payload of gpd commissioning command according to A.4.2.1.1 GPD Commissioning command from docs-14-0563-16-batt-green-power-spec_ProxyBasic.pdf */ From 3b1739e5d02745ab755b31bc3072ba1e153f1420 Mon Sep 17 00:00:00 2001 From: Lionel Ains Date: Fri, 22 Nov 2019 12:43:52 +0100 Subject: [PATCH 37/44] Lining-up code to compile in Raritan's framework --- src/Makefile | 84 ++++++++----------- src/domain/custom-aes.cpp | 26 +++--- .../ember-gp-sink-table-options-field.cpp | 18 ++-- .../ember-gp-sink-table-options-field.h | 6 +- .../ember-process-gp-pairing-parameter.h | 6 +- .../gp-pairing-command-option-struct.cpp | 21 +++-- .../gp-pairing-command-option-struct.h | 8 +- .../gpd-commissioning-command-payload.cpp | 14 ++-- src/example/CAppDemo.cpp | 8 +- src/example/CAppDemo.h | 5 +- src/libezsp.mk.inc | 14 +++- 11 files changed, 115 insertions(+), 95 deletions(-) diff --git a/src/Makefile b/src/Makefile index 4dad4fb3..67b1a3b9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,71 +9,59 @@ TARGET_SHARED_LIBNAMES = libezsp libezsp_MODULE_NAME = test_log -libezsp_SRCS = domain/zbmessage/zigbee-message.cpp \ - domain/zbmessage/zclheader.cpp \ - domain/zbmessage/zclframecontrol.cpp \ - domain/zbmessage/apsoption.cpp \ - domain/zbmessage/aps.cpp \ - domain/zbmessage/zdp-enum.cpp \ - domain/zbmessage/green-power-device.cpp \ - domain/zbmessage/green-power-frame.cpp \ - domain/zigbee-tools/green-power-sink.cpp \ - domain/zbmessage/green-power-sink-table-entry.cpp \ - domain/zigbee-tools/zigbee-messaging.cpp \ - domain/zigbee-tools/zigbee-networking.cpp \ - domain/zigbee-tools/green-power-sink-table.cpp \ - domain/ezsp-protocol/ezsp-enum.cpp \ - domain/ezsp-protocol/get-network-parameters-response.cpp \ - domain/ezsp-protocol/struct/ember-key-struct.cpp \ - domain/ezsp-protocol/struct/ember-network-parameters.cpp \ - domain/ezsp-protocol/struct/ember-child-data-struct.cpp \ - domain/ezsp-protocol/struct/ember-gp-address-struct.cpp \ - domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.cpp \ - domain/ezsp-dongle.cpp \ - domain/ash.cpp \ - spi/GenericAsyncDataInputObservable.cpp \ - spi/raritan/RaritanUartDriver.cpp \ - spi/raritan/RaritanTimerFactory.cpp \ - spi/raritan/RaritanTimer.cpp \ - spi/raritan/RaritanEventLoop.cpp \ - spi/raritan/RaritanLogger.cpp \ +# SRC_PATH should point to the src/ folder containing source code for this library (can be overridden from environment) +SRC_PATH ?= . +SRC_DOMAIN_PATH ?= $(SRC_PATH)/domain +SRC_SPI_PATH ?= $(SRC_PATH)/spi + +include libezsp.mk.inc + +libezsp_SRCS = $(LIBEZSP_RARITAN_SRC) libezsp_LIBS = -lpp_base # Header files to install libezspincludedir = $(includedir)/include/local/ezsp -libezspinclude_HEADERS = domain/zbmessage/zdp-enum.h \ -domain/ezsp-protocol/ezsp-enum.h \ -domain/ezsp-protocol/get-network-parameters-response.h \ -domain/byte-manip.h \ -domain/ash.h \ -domain/ezsp-dongle.h \ -domain/ezsp-dongle-observer.h \ +libezspinclude_HEADERS = \ domain/zigbee-tools/zigbee-networking.h \ -domain/zigbee-tools/zigbee-messaging.h \ -domain/zbmessage/green-power-frame.h \ -domain/zigbee-tools/green-power-sink.h \ domain/zigbee-tools/green-power-sink-table.h \ -domain/zbmessage/green-power-sink-table-entry.h \ +domain/zigbee-tools/green-power-sink.h \ +domain/zigbee-tools/zigbee-messaging.h \ domain/green-power-observer.h \ -domain/zbmessage/zigbee-message.h \ -domain/zbmessage/aps.h \ -domain/zbmessage/apsoption.h \ -domain/zbmessage/zclheader.h \ -domain/zbmessage/zclframecontrol.h \ +domain/ezsp-dongle-observer.h \ +domain/ezsp-dongle.h \ +domain/ash.h \ +domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h \ domain/ezsp-protocol/struct/ember-key-struct.h \ -domain/ezsp-protocol/struct/ember-network-parameters.h \ +domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h \ +domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h \ domain/ezsp-protocol/struct/ember-child-data-struct.h \ +domain/ezsp-protocol/struct/ember-network-parameters.h \ domain/ezsp-protocol/struct/ember-gp-address-struct.h \ -domain/ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h \ +domain/ezsp-protocol/get-network-parameters-response.h \ +domain/ezsp-protocol/ezsp-enum.h \ +domain/zbmessage/green-power-device.h \ +domain/zbmessage/green-power-frame.h \ +domain/zbmessage/gp-pairing-command-option-struct.h \ +domain/zbmessage/aps.h \ +domain/zbmessage/zclframecontrol.h \ +domain/zbmessage/zclheader.h \ +domain/zbmessage/apsoption.h \ +domain/zbmessage/green-power-sink-table-entry.h \ +domain/zbmessage/gpd-commissioning-command-payload.h \ +domain/zbmessage/zdp-enum.h \ +domain/zbmessage/zigbee-message.h \ +spi/raritan/RaritanLogger.h \ spi/raritan/RaritanTimerFactory.h \ +spi/raritan/RaritanTimer.h \ spi/raritan/RaritanEventLoop.h \ spi/raritan/RaritanUartDriver.h \ +spi/ILogger.h \ spi/ITimerFactory.h \ -spi/ITimerFactory.h \ -spi/IUartDriver.h \ spi/ITimer.h \ +spi/IUartDriver.h \ +spi/GenericLogger.h \ spi/GenericAsyncDataInputObservable.h \ spi/IAsyncDataInputObserver.h \ diff --git a/src/domain/custom-aes.cpp b/src/domain/custom-aes.cpp index 42d6da6b..d2132343 100644 --- a/src/domain/custom-aes.cpp +++ b/src/domain/custom-aes.cpp @@ -60,18 +60,18 @@ CAes::CAes() : // algorithm void CAes::xor_block( void *d, const void *s ) { - ((uint32_t*)d)[ 0] ^= ((uint32_t*)s)[ 0]; - ((uint32_t*)d)[ 1] ^= ((uint32_t*)s)[ 1]; - ((uint32_t*)d)[ 2] ^= ((uint32_t*)s)[ 2]; - ((uint32_t*)d)[ 3] ^= ((uint32_t*)s)[ 3]; + (static_cast(d))[ 0] ^= (static_cast(s))[ 0]; + (static_cast(d))[ 1] ^= (static_cast(s))[ 1]; + (static_cast(d))[ 2] ^= (static_cast(s))[ 2]; + (static_cast(d))[ 3] ^= (static_cast(s))[ 3]; } void CAes::copy_and_key( void *d, const void *s, const void *k ) { - ((uint32_t*)d)[ 0] = ((uint32_t*)s)[ 0] ^ ((uint32_t*)k)[ 0]; - ((uint32_t*)d)[ 1] = ((uint32_t*)s)[ 1] ^ ((uint32_t*)k)[ 1]; - ((uint32_t*)d)[ 2] = ((uint32_t*)s)[ 2] ^ ((uint32_t*)k)[ 2]; - ((uint32_t*)d)[ 3] = ((uint32_t*)s)[ 3] ^ ((uint32_t*)k)[ 3]; + (static_cast(d))[ 0] = (static_cast(s))[ 0] ^ (static_cast(k))[ 0]; + (static_cast(d))[ 1] = (static_cast(s))[ 1] ^ (static_cast(k))[ 1]; + (static_cast(d))[ 2] = (static_cast(s))[ 2] ^ (static_cast(k))[ 2]; + (static_cast(d))[ 3] = (static_cast(s))[ 3] ^ (static_cast(k))[ 3]; } void CAes::add_round_key( uint8_t d[N_BLOCK], const uint8_t k[N_BLOCK] ) @@ -174,9 +174,9 @@ void CAes::aes_set_key( const uint8_t key[AES_KEY_SIZE] ) uint8_t keylen = AES_KEY_SIZE; block_copy_nn(ctx->ksch, key, keylen); - hi = (keylen + 28) << 2; - ctx->rnd = (hi >> 4) - 1; - for( cc = keylen, rc = 1; cc < hi; cc += 4 ) + hi = static_cast(static_cast(keylen + 28) << 2); + ctx->rnd = static_cast((hi >> 4) - 1); + for( cc = keylen, rc = 1; cc < hi; cc = static_cast(cc + 4) ) { uint8_t tt, t0, t1, t2, t3; t0 = ctx->ksch[cc - 4]; @@ -190,7 +190,7 @@ void CAes::aes_set_key( const uint8_t key[AES_KEY_SIZE] ) t1 = s_box(t2); t2 = s_box(t3); t3 = s_box(tt); - rc = f2(rc); + rc = static_cast(f2(rc)); } else if( keylen > 24 && cc % keylen == 16 ) { @@ -199,7 +199,7 @@ void CAes::aes_set_key( const uint8_t key[AES_KEY_SIZE] ) t2 = s_box(t2); t3 = s_box(t3); } - tt = cc - keylen; + tt = static_cast(cc - keylen); ctx->ksch[cc + 0] = ctx->ksch[tt + 0] ^ t0; ctx->ksch[cc + 1] = ctx->ksch[tt + 1] ^ t1; ctx->ksch[cc + 2] = ctx->ksch[tt + 2] ^ t2; diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp index 8db364e9..eda8dd12 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.cpp @@ -114,14 +114,14 @@ CEmberGpSinkTableOption& CEmberGpSinkTableOption::operator=( CEmberGpSinkTableOp */ uint16_t CEmberGpSinkTableOption::get() const { - uint16_t o_options = 0 + \ - application_id + \ - (communication_mode<<3) + \ - (sequence_number_capabilities<<5) + \ - (rx_on_capability<<6) + \ - (fixed_location<<7) + \ - (assigned_alias<<8) + \ - (security_use<<9); + uint16_t o_options; + o_options = static_cast(application_id<<0); + o_options |= static_cast(communication_mode<<3); + o_options |= static_cast(sequence_number_capabilities<<5); + o_options |= static_cast(rx_on_capability<<6); + o_options |= static_cast(fixed_location<<7); + o_options |= static_cast(assigned_alias<<8); + o_options |= static_cast(security_use<<9); return o_options; } @@ -146,4 +146,4 @@ std::string CEmberGpSinkTableOption::String() const std::ostream& operator<< (std::ostream& out, const CEmberGpSinkTableOption& data){ out << data.String(); return out; -} \ No newline at end of file +} diff --git a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h index 7fe9246c..fb9e7cc9 100644 --- a/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h +++ b/src/domain/ezsp-protocol/struct/ember-gp-sink-table-options-field.h @@ -152,4 +152,8 @@ class CEmberGpSinkTableOption bool fixed_location; /*!< The fixed location toggle contained in this sink table entry options bit field */ bool assigned_alias; /*!< The assigned alias toggle contained in this sink table entry options bit field */ bool security_use; /*!< The security use toggle contained in this sink table entry options bit field */ -}; \ No newline at end of file +}; + +#ifdef USE_RARITAN +#include +#endif // USE_RARITAN diff --git a/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h b/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h index fad82133..aa0054b6 100644 --- a/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h +++ b/src/domain/ezsp-protocol/struct/ember-process-gp-pairing-parameter.h @@ -68,4 +68,8 @@ class CProcessGpPairingParam EmberKeyData gpdKey; /*!< The key to use for the target GPD */ uint32_t gpdSecurityFrameCounter; /*!< The gpd security frame counter */ uint8_t forwardingRadius; /*!< The forwarding radius */ -}; \ No newline at end of file +}; + +#ifdef USE_RARITAN +#include +#endif // USE_RARITAN diff --git a/src/domain/zbmessage/gp-pairing-command-option-struct.cpp b/src/domain/zbmessage/gp-pairing-command-option-struct.cpp index cf8d35a1..90bd8ff4 100644 --- a/src/domain/zbmessage/gp-pairing-command-option-struct.cpp +++ b/src/domain/zbmessage/gp-pairing-command-option-struct.cpp @@ -7,7 +7,7 @@ #include "gp-pairing-command-option-struct.h" CGpPairingCommandOption::CGpPairingCommandOption(CEmberGpSinkTableOption i_sink_table_option, bool i_add_sink, bool i_remove_gpd, - uint8_t i_security_level, uint8_t i_security_key_type, bool i_frm_counter_present, + uint8_t i_security_level, uint8_t i_security_key_type, bool i_frm_counter_present, bool i_key_present, bool i_radius_present ): application_id(i_sink_table_option.getApplicationId()), add_sink(i_add_sink), @@ -27,11 +27,20 @@ CGpPairingCommandOption::CGpPairingCommandOption(CEmberGpSinkTableOption i_sink_ uint32_t CGpPairingCommandOption::get() const { - uint32_t lo_option = 0; + uint32_t lo_option; - lo_option = (application_id<<0) | (add_sink<<3) | (remove_gpd<<4) | (communication_mode<<5) | (gpd_fixed<<7) | (gpd_mac_seq_number_capability<<8) | - (security_level<<9) | (security_key_type<<11) | (gpd_security_frame_counter_present<<14) | (gpd_security_key_present<<15) | - (assigned_alias_present<<16) | (forwarding_radius_present<<17) | 0; + lo_option = static_cast(application_id<<0); + lo_option |= static_cast(add_sink<<3); + lo_option |= static_cast(remove_gpd<<4); + lo_option |= static_cast(communication_mode<<5); + lo_option |= static_cast(gpd_fixed<<7); + lo_option |= static_cast(gpd_mac_seq_number_capability<<8); + lo_option |= static_cast(security_level<<9); + lo_option |= static_cast(security_key_type<<11); + lo_option |= static_cast(gpd_security_frame_counter_present<<14); + lo_option |= static_cast(gpd_security_key_present<<15); + lo_option |= static_cast(assigned_alias_present<<16); + lo_option |= static_cast(forwarding_radius_present<<17); - return lo_option; + return lo_option; } diff --git a/src/domain/zbmessage/gp-pairing-command-option-struct.h b/src/domain/zbmessage/gp-pairing-command-option-struct.h index c8a59e6d..79abcb1b 100644 --- a/src/domain/zbmessage/gp-pairing-command-option-struct.h +++ b/src/domain/zbmessage/gp-pairing-command-option-struct.h @@ -117,7 +117,7 @@ class CGpPairingCommandOption * carries the Alias value to be used for this GPD instead of the derived alias. */ bool assigned_alias_present; /*!< Represents whether the AssignedAlias field is present and carries the Alias value to be used for this GPD instead of the derived alias */ - /** + /** * Bit 17: The Forwarding Radius present sub-field, if set to 0b1, indicates that the Forwarding Radius field is * present and carries the Forwarding Radius value to be used as value of the radius in the groupcast forwarding * of the GPDF packet. If the Forwarding Radius field is not present, and a new Proxy Table entry is to be created, @@ -128,4 +128,8 @@ class CGpPairingCommandOption /** * Bit 18..23: Reserved */ -}; \ No newline at end of file +}; + +#ifdef USE_RARITAN +#include +#endif // USE_RARITAN diff --git a/src/domain/zbmessage/gpd-commissioning-command-payload.cpp b/src/domain/zbmessage/gpd-commissioning-command-payload.cpp index 0f534f87..2aa432c2 100644 --- a/src/domain/zbmessage/gpd-commissioning-command-payload.cpp +++ b/src/domain/zbmessage/gpd-commissioning-command-payload.cpp @@ -26,7 +26,7 @@ CGpdCommissioningPayload::CGpdCommissioningPayload(const std::vector& r gpd_cluster_list() { // only device_id and option are mandatory, other field depend of option value - uint8_t l_idx = 2; + unsigned int l_idx = 2; // extended option if( options & (1<& r // gpd key if( extended_options & (1<(l_idx),raw_message.begin()+static_cast(l_idx)+EMBER_KEY_DATA_BYTE_SIZE); l_idx += EMBER_KEY_DATA_BYTE_SIZE; // gpd key MIC and encryption if( extended_options & (1<& r //construct nonce memset(nonce,0,16); nonce[0] = 0x01; - memcpy(&nonce[1], (uint8_t *)&i_src_id, 4); - memcpy(&nonce[5], (uint8_t *)&i_src_id, 4); - memcpy(&nonce[9], (uint8_t *)&i_src_id, 4); + memcpy(&nonce[1], static_cast(&i_src_id), 4); + memcpy(&nonce[5], static_cast(&i_src_id), 4); + memcpy(&nonce[9], static_cast(&i_src_id), 4); nonce[13] = 0x05; nonce[14]=0x00; nonce[15]=0x01; @@ -124,7 +124,7 @@ CGpdCommissioningPayload::CGpdCommissioningPayload(const std::vector& r // gpd cluster list if( app_information & (1<(l_idx),raw_message.end()); } } @@ -158,4 +158,4 @@ std::string CGpdCommissioningPayload::String() const std::ostream& operator<< (std::ostream& out, const CGpdCommissioningPayload& data){ out << data.String(); return out; -} \ No newline at end of file +} diff --git a/src/example/CAppDemo.cpp b/src/example/CAppDemo.cpp index 78d2a214..1ccb6b8f 100644 --- a/src/example/CAppDemo.cpp +++ b/src/example/CAppDemo.cpp @@ -23,7 +23,7 @@ CAppDemo::CAppDemo(IUartDriver& uartDriver, bool openGpCommissionning, bool openZigbeeCommissionning, unsigned int networkChannel, - const std::vector& gpDevList) : + const std::vector& gpDevicesList) : dongle(i_timer_factory, this), zb_messaging(dongle, i_timer_factory), zb_nwk(dongle, zb_messaging), @@ -35,7 +35,7 @@ CAppDemo::CAppDemo(IUartDriver& uartDriver, openGpCommissionningAtStartup(openGpCommissionning), openZigbeeCommissionningAtStartup(openZigbeeCommissionning), channel(networkChannel), - gpDevList(gpDevList) + gpdList(gpDevicesList) { setAppState(APP_NOT_INIT); // uart @@ -190,7 +190,7 @@ bool CAppDemo::extractMultiClusterReport( std::vector payload ) validBuffer = extractClusterReport(payload, usedBytes); if (validBuffer) { - payload.erase(payload.begin(), payload.begin()+usedBytes); + payload.erase(payload.begin(), payload.begin()+static_cast(usedBytes)); } } return validBuffer; @@ -279,7 +279,7 @@ void CAppDemo::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_r } else { - for (auto i : this->gpDevList) { + for (auto i : this->gpdList) { clogD << "Adding source ID 0x" << std::hex << std::setw(8) << std::setfill('0') << i.getSourceId() << " to monitored devices\n"; gp_sink.registerGpd(i); } diff --git a/src/example/CAppDemo.h b/src/example/CAppDemo.h index 93f9c9c8..a6ace9bd 100644 --- a/src/example/CAppDemo.h +++ b/src/example/CAppDemo.h @@ -29,7 +29,7 @@ typedef enum class CAppDemo : public CEzspDongleObserver, CGpObserver { public: - CAppDemo(IUartDriver& uartDriver, ITimerFactory &i_timer_factory, bool reset=false, bool openGpCommissionning=false, bool openZigbeeCommissionning=false, unsigned int networkChannel=11, const std::vector& gpDevList={}); + CAppDemo(IUartDriver& uartDriver, ITimerFactory &i_timer_factory, bool reset=false, bool openGpCommissionning=false, bool openZigbeeCommissionning=false, unsigned int networkChannel=11, const std::vector& gpDevicesList={}); /** * Callback @@ -59,6 +59,5 @@ class CAppDemo : public CEzspDongleObserver, CGpObserver bool openGpCommissionningAtStartup; /* Do we open GP commissionning at dongle initialization? */ bool openZigbeeCommissionningAtStartup; /* Do we open the Zigbee network at dongle initialization? */ unsigned int channel; /*!< The Zigbee channel on which to create the network (if reset_wanted is set) */ - std::vector gpDevList; /*!< The list of GP devices we are monitoring */ + std::vector gpdList; /*!< The list of GP devices we are monitoring */ }; - diff --git a/src/libezsp.mk.inc b/src/libezsp.mk.inc index 3d1d31ba..beb3332e 100644 --- a/src/libezsp.mk.inc +++ b/src/libezsp.mk.inc @@ -33,6 +33,14 @@ LIBEZSP_LINUX_SPI_SRC = \ $(SRC_SPI_PATH)/cppthreads/CppThreadsTimerFactory.cpp \ $(SRC_SPI_PATH)/cppthreads/CppThreadsTimer.cpp \ +LIBEZSP_RARITAN_SPI_SRC = \ + $(SRC_SPI_PATH)/GenericAsyncDataInputObservable.cpp \ + $(SRC_SPI_PATH)/raritan/RaritanUartDriver.cpp \ + $(SRC_SPI_PATH)/raritan/RaritanTimerFactory.cpp \ + $(SRC_SPI_PATH)/raritan/RaritanTimer.cpp \ + $(SRC_SPI_PATH)/raritan/RaritanEventLoop.cpp \ + $(SRC_SPI_PATH)/raritan/RaritanLogger.cpp \ + LIBEZSP_LINUX_SERIALCPP_SRC = $(LIBEZSP_COMMON_SRC) \ $(LIBEZSP_LINUX_SPI_SRC) \ $(SRC_SPI_PATH)/serial/SerialUartDriver.cpp \ @@ -41,9 +49,13 @@ LIBEZSP_LINUX_MOCKSERIAL_SRC = $(LIBEZSP_COMMON_SRC) \ $(LIBEZSP_LINUX_SPI_SRC) \ $(SRC_SPI_PATH)/mock-uart/MockUartDriver.cpp \ +LIBEZSP_RARITAN_SRC = $(LIBEZSP_COMMON_SRC) \ + $(LIBEZSP_RARITAN_SPI_SRC) \ + LIBEZSP_COMMON_INC = -I$(SRC_SPI_PATH) -I$(SRC_DOMAIN_PATH) -I$(SRC_DOMAIN_PATH)/zbmessage export LIBEZSP_COMMON_SRC export LIBEZSP_LINUX_SERIALCPP_SRC export LIBEZSP_LINUX_MOCKSERIAL_SRC -export LIBEZSP_COMMON_INC \ No newline at end of file +export LIBEZSP_RARITAN_SPI_SRC +export LIBEZSP_COMMON_INC From 025f96d8347347dd3bd20b2ae6e5b939fecfb697 Mon Sep 17 00:00:00 2001 From: seb Date: Fri, 22 Nov 2019 14:04:08 +0100 Subject: [PATCH 38/44] adding optional field for register a gpd --- src/domain/zbmessage/green-power-device.cpp | 25 ++++++++++++++++- src/domain/zbmessage/green-power-device.h | 31 +++++++++++++++++++-- src/example/CAppDemo.cpp | 9 ++---- 3 files changed, 55 insertions(+), 10 deletions(-) diff --git a/src/domain/zbmessage/green-power-device.cpp b/src/domain/zbmessage/green-power-device.cpp index 53bb099c..d382ce7f 100644 --- a/src/domain/zbmessage/green-power-device.cpp +++ b/src/domain/zbmessage/green-power-device.cpp @@ -8,10 +8,33 @@ CGpDevice::CGpDevice(uint32_t i_source_id, const EmberKeyData& i_key) : source_id(i_source_id), - key(i_key) + key(i_key), + option(0x02A8), + security_option(0x12) { } +/** + * This method is a friend of CEmberGpSinkTableOption class + * swap() is needed within operator=() to implement to copy and swap paradigm +**/ +void swap(CGpDevice& first, CGpDevice& second) /* nothrow */ +{ + using std::swap; // Enable ADL + + swap(first.source_id, second.source_id); + swap(first.key, second.key); + swap(first.option, second.option); + swap(first.security_option, second.security_option); + /* Once we have swapped the members of the two instances... the two instances have actually been swapped */ +} + +CGpDevice& CGpDevice::operator=( CGpDevice other) +{ + swap(*this, other); + return *this; +} + uint32_t CGpDevice::getSourceId() const { return this->source_id; diff --git a/src/domain/zbmessage/green-power-device.h b/src/domain/zbmessage/green-power-device.h index 692520d7..48441e45 100644 --- a/src/domain/zbmessage/green-power-device.h +++ b/src/domain/zbmessage/green-power-device.h @@ -8,6 +8,7 @@ #include #include "../ezsp-protocol/ezsp-enum.h" +#include "../ezsp-protocol/struct/ember-gp-sink-table-options-field.h" /** * @brief Class to encapsulate data representing a green power device @@ -34,9 +35,19 @@ class CGpDevice /** * @brief Assignment operator * - * Copy construction is forbidden on this class */ - CGpDevice& operator=(const CGpDevice& other) = delete; + CGpDevice& operator=(const CGpDevice other); + + /** + * @brief swap function to allow implementing of copy-and-swap idiom on members of type CEmberGpSinkTableOption + * + * This function will swap all attributes of \p first and \p second + * See http://stackoverflow.com/questions/3279543/what-is-the-copy-and-swap-idiom + * + * @param first The first object + * @param second The second object + */ + friend void (::swap)(CGpDevice& first, CGpDevice& second); /** * @brief Retrieve the source id for this device @@ -52,7 +63,23 @@ class CGpDevice */ EmberKeyData getKey() const; + /** + * @brief Retrieve the sink option table for this device + * + * @return The option + */ + CEmberGpSinkTableOption getSinkOption() const { return option; } + + /** + * @brief Retrieve the sink security option table for this device + * + * @return The security option + */ + uint8_t getSinkSecurityOption() const { return security_option; } + private: uint32_t source_id; /*!< The source ID for this device */ EmberKeyData key; /*!< The key for this device */ + CEmberGpSinkTableOption option; /*!< Sink table option for this device */ + uint8_t security_option; /*!< Sink table security option for this device */ }; diff --git a/src/example/CAppDemo.cpp b/src/example/CAppDemo.cpp index 78d2a214..bd72688b 100644 --- a/src/example/CAppDemo.cpp +++ b/src/example/CAppDemo.cpp @@ -277,14 +277,9 @@ void CAppDemo::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_r // If requested to do so, immediately open a GP commissioning session gp_sink.openCommissioningSession(); } - else + else if( gpDevList.size() ) { - for (auto i : this->gpDevList) { - clogD << "Adding source ID 0x" << std::hex << std::setw(8) << std::setfill('0') << i.getSourceId() << " to monitored devices\n"; - gp_sink.registerGpd(i); - } - // debug : add hardcoded gpd - //gp_sink.registerGpd(CGpDevice(0x00510050,{0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x0E,0x0F})); + gp_sink.registerGpds(gpDevList); } From 3590e1e6e27c2a31b4d8dab2f1d3cdf07ff2094e Mon Sep 17 00:00:00 2001 From: seb Date: Fri, 22 Nov 2019 14:05:01 +0100 Subject: [PATCH 39/44] register a list of gpd --- src/domain/zigbee-tools/green-power-sink.cpp | 56 +++++++++----------- src/domain/zigbee-tools/green-power-sink.h | 14 ++--- 2 files changed, 27 insertions(+), 43 deletions(-) diff --git a/src/domain/zigbee-tools/green-power-sink.cpp b/src/domain/zigbee-tools/green-power-sink.cpp index 52c2b822..e897d304 100644 --- a/src/domain/zigbee-tools/green-power-sink.cpp +++ b/src/domain/zigbee-tools/green-power-sink.cpp @@ -65,10 +65,10 @@ CGpSink::CGpSink( CEzspDongle &i_dongle, CZigbeeMessaging &i_zb_messaging ) : dongle(i_dongle), zb_messaging(i_zb_messaging), - sink_table(), sink_state(SINK_NOT_INIT), gpf_comm_frame(), sink_table_index(0xFF), + gpds_to_register(), sink_table_entry(), observers() { @@ -109,22 +109,13 @@ void CGpSink::closeCommissioningSession() setSinkState(SINK_READY); } -uint8_t CGpSink::registerGpd( uint32_t i_source_id ) -{ - CGpSinkTableEntry l_entry = CGpSinkTableEntry(i_source_id); - - return sink_table.addEntry(l_entry); -} - -void CGpSink::registerGpd( const CGpDevice &gpd ) +void CGpSink::registerGpds( const std::vector &gpd ) { // save offline information - CEmberGpAddressStruct l_gp_addr(gpd.getSourceId()); - sink_table_entry.setGpdAddress(l_gp_addr); - sink_table_entry.setKey(gpd.getKey()); + gpds_to_register = gpd; // request sink table entry - gpSinkTableFindOrAllocateEntry( gpd.getSourceId() ); + gpSinkTableFindOrAllocateEntry( gpds_to_register.back().getSourceId() ); // set state setSinkState(SINK_COM_OFFLINE_IN_PROGRESS); @@ -180,9 +171,6 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re if( GPD_NO_SECURITY == gpf.getSecurity() ) { - // to test notify - notifyObserversOfRxGpFrame( gpf ); - // if we are in Commissioning and this is a commissioning frame : use it ! if( (SINK_COM_OPEN == sink_state) && (GPF_COMMISSIONING_CMD == gpf.getCommandId()) ) { @@ -203,15 +191,6 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re { notifyObserversOfRxGpFrame( gpf ); } - /* - // look up if product is register - uint8_t l_sink_entry_idx = sink_table.getEntryIndexForSourceId( gpf.getSourceId() ); - if( GP_SINK_INVALID_ENTRY != l_sink_entry_idx ) - { - // to test notify - notifyObserversOfRxGpFrame( gpf ); - } - */ } } break; @@ -308,13 +287,15 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re clogD << "EZSP_GP_SINK_TABLE_GET_ENTRY Response status :" << CEzspEnum::EEmberStatusToString(l_status) << ", table entry : " << l_entry << std::endl; // update sink table entry + CEmberGpAddressStruct l_gp_addr(gpds_to_register.back().getSourceId()); + l_entry.setEntryActive(true); - l_entry.setOptions(0x02A8); // \todo WARNING HARDCODED VALUE - l_entry.setGpdAddress(sink_table_entry.getGpdAddr()); - l_entry.setAlias(static_cast(sink_table_entry.getGpdAddr().getSourceId()&0xFFFF)); - l_entry.setSecurityOption(0x12); // \todo WARNING HARDCODED VALUE + l_entry.setOptions(gpds_to_register.back().getSinkOption()); + l_entry.setGpdAddress(l_gp_addr); + l_entry.setAlias(static_cast(l_gp_addr.getSourceId()&0xFFFF)); + l_entry.setSecurityOption(gpds_to_register.back().getSinkSecurityOption()); l_entry.setFrameCounter(0); - l_entry.setKey(sink_table_entry.getGpdKey()); + l_entry.setKey(gpds_to_register.back().getKey()); // debug clogD << "Update table entry : " << l_entry << std::endl; @@ -368,8 +349,18 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re { clogI << "CGpSink::ezspHandler EZSP_GP_PROXY_TABLE_PROCESS_GP_PAIRING gpPairingAdded : " << std::hex << std::setw(2) << std::setfill('0') << static_cast(i_msg_receive[0]) << std::endl; - // set state - setSinkState(SINK_READY); + gpds_to_register.pop_back(); + + if( gpds_to_register.size() ) + { + // request sink table entry + gpSinkTableFindOrAllocateEntry( gpds_to_register.back().getSourceId() ); + } + else + { + // set state + setSinkState(SINK_READY); + } } } break; @@ -623,6 +614,7 @@ void CGpSink::setSinkState( ESinkState i_state ) { SINK_ERROR, "SINK_ERROR" }, { SINK_COM_OPEN, "SINK_COM_OPEN" }, { SINK_COM_IN_PROGRESS, "SINK_COM_IN_PROGRESS" }, + { SINK_COM_OFFLINE_IN_PROGRESS, "SINK_COM_OFFLINE_IN_PROGRESS" }, }; auto it = MyEnumStrings.find(sink_state); /* FIXME: we issue a warning, but the variable app_state is now out of bounds */ diff --git a/src/domain/zigbee-tools/green-power-sink.h b/src/domain/zigbee-tools/green-power-sink.h index 4299045d..7e7b8105 100644 --- a/src/domain/zigbee-tools/green-power-sink.h +++ b/src/domain/zigbee-tools/green-power-sink.h @@ -11,7 +11,6 @@ #include "../green-power-observer.h" #include "../ezsp-dongle.h" #include "zigbee-messaging.h" -#include "green-power-sink-table.h" #include "../ezsp-protocol/struct/ember-gp-sink-table-entry-struct.h" #include "../ezsp-protocol/struct/ember-process-gp-pairing-parameter.h" @@ -60,19 +59,12 @@ class CGpSink : public CEzspDongleObserver */ void closeCommissioningSession(); - /** - * @brief add a green power sink table entry - * - * @return index of entry in sink table, or GP_SINK_INVALID_ENTRY if table is full - */ - uint8_t registerGpd( uint32_t i_source_id ); - /** * @brief Add a green power device to this sink * - * @param gpd The description oof the device to add + * @param gpd list of gpds to add */ - void registerGpd( const CGpDevice &gpd ); + void registerGpds( const std::vector &gpd ); /** * Observer @@ -90,11 +82,11 @@ class CGpSink : public CEzspDongleObserver private: CEzspDongle &dongle; CZigbeeMessaging &zb_messaging; - CGpSinkTable sink_table; ESinkState sink_state; // parameters to save for pairing CGpFrame gpf_comm_frame; uint8_t sink_table_index; + std::vector gpds_to_register; CEmberGpSinkTableEntryStruct sink_table_entry; std::set observers; /*!< List of observers of this class */ From b1b5d0c9d28f47a5e70618a766f1389ca06ef151 Mon Sep 17 00:00:00 2001 From: Lionel AINS Date: Fri, 22 Nov 2019 14:12:09 +0100 Subject: [PATCH 40/44] Improving error handling on hex key decoding --- src/example/mainEzspTest.cpp | 42 +++++++++++++++++++++++++++++++----- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/src/example/mainEzspTest.cpp b/src/example/mainEzspTest.cpp index 3a862ecc..cbf05f62 100644 --- a/src/example/mainEzspTest.cpp +++ b/src/example/mainEzspTest.cpp @@ -41,6 +41,23 @@ static void writeUsage(const char* progname, FILE *f) { fprintf(f,"-s (--source-id) : adds a device to the monitored list, based on its source-id & key, id being formatted as a 8-digit hexadecimal string (eg: 'ffae1245'), and key as a 16-byte/32-digit hex string (repeated -s options are allowed)\n"); } +/** + * @brief Convert an ASCII character representing one hexadecimal digit ([0-9a-fA-F]) to its value (0-15) + * + * @param hDigit The input printable ASCII character + * @return The value of the hexadecimal digit as a uint8_t nibble (0-15) +**/ +uint8_t hexDigitToNibble(const char hDigit) { + if (hDigit>='a' && hDigit<='f') + return static_cast(hDigit + 10 - 'a'); + else if (hDigit>='A' && hDigit<='F') + return static_cast(hDigit + 10 - 'A'); + else if (hDigit>='0' && hDigit<='9') + return static_cast(hDigit - '0'); + else + throw std::out_of_range("Invalid character '" + std::string(1, hDigit) + "'"); +} + int main(int argc, char **argv) { #ifdef USE_SERIALCPP SerialUartDriver uartDriver; @@ -90,15 +107,30 @@ int main(int argc, char **argv) { gpDevDataStream >> gpDevKeyStr; /* Read everything after the separator, which should be the key */ //std::cerr << "Read key part of arg: " << gpDevKeyStr << "\n"; if (gpDevKeyStr.length() != 32) { - clogE << "Invalid key length: " << gpDevKeyStr << " (should be 16-bytes long). Ignoring this entry\n"; + clogE << "Invalid key length: " << gpDevKeyStr << " (should be 16-bytes long).\n"; + exit(1); } else { EmberKeyData keyValue(CGpDevice::UNKNOWN_KEY); if (gpDevKeyStr != "") { - std::vector argAsBytes; - for (unsigned int i = 0; i < gpDevKeyStr.length(); i += 2){ - std::string byteString = gpDevKeyStr.substr(i, 2); - argAsBytes.push_back(static_cast(strtol(byteString.c_str(), NULL, 16))); + std::vector argAsBytes; + for (unsigned int i = 0; i < gpDevKeyStr.length(); i += 2) { + uint8_t byte; + try { + byte = hexDigitToNibble(gpDevKeyStr[i]) << 4; + } + catch (const std::out_of_range& e) { + clogE << "Invalid character '" << gpDevKeyStr[i] << "' at position " << i+1 << " in key " << gpDevKeyStr << "\n"; /* Note: 1st char is identified by a position=1 for readability */ + exit(1); + } + try { + byte |= hexDigitToNibble(gpDevKeyStr[i+1]); + } + catch (const std::out_of_range& e) { + clogE << "Invalid character '" << gpDevKeyStr[i+1] << "' at position " << i+2 << " in key " << gpDevKeyStr << "\n"; /* Note: 1st char is identified by a position=1 for readability */ + exit(1); + } + argAsBytes.push_back(byte); } //for (uint8_t loop=0; loop Date: Fri, 22 Nov 2019 14:21:58 +0100 Subject: [PATCH 41/44] remove unused class --- .../zigbee-tools/green-power-sink-table.cpp | 83 ------------------- .../zigbee-tools/green-power-sink-table.h | 50 ----------- src/domain/zigbee-tools/green-power-sink.cpp | 15 +--- src/libezsp.mk.inc | 1 - 4 files changed, 1 insertion(+), 148 deletions(-) delete mode 100644 src/domain/zigbee-tools/green-power-sink-table.cpp delete mode 100644 src/domain/zigbee-tools/green-power-sink-table.h diff --git a/src/domain/zigbee-tools/green-power-sink-table.cpp b/src/domain/zigbee-tools/green-power-sink-table.cpp deleted file mode 100644 index 4c1b3eab..00000000 --- a/src/domain/zigbee-tools/green-power-sink-table.cpp +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @file green-power-sink-table.cpp - * - * @brief A green power sink table - */ - -#include -#include - -#include "green-power-sink-table.h" - -#include "../../spi/GenericLogger.h" -#include "../../spi/ILogger.h" - -CGpSinkTable::CGpSinkTable() : - gpds() -{ - -} - -uint8_t CGpSinkTable::addEntry( CGpSinkTableEntry i_entry ) -{ - uint8_t lo_index = GP_SINK_INVALID_ENTRY; - -/* - std::stringstream buf; - buf << "[source_id : "<< std::hex << std::setw(8) << std::setfill('0') << unsigned(i_entry.getSourceId()) << "]"; - clogI << "CGpSinkTable::addEntry : " << buf.str() << std::endl; -*/ - // loop on table to search if gpd is already register - lo_index = getEntryIndexForSourceId( i_entry.getSourceId() ); - if( GP_SINK_INVALID_ENTRY == lo_index ) - { - // limit number of entry ! - if( gpds.size() < GP_SINK_INVALID_ENTRY ) - { - if (gpds.size()>255) - { - clogW << "gpd table size overflow\n"; - } - else - { - lo_index = static_cast(gpds.size()); - gpds.push_back(i_entry); - } - } - } - -// clogI << "CGpSinkTable::addEntry at index : " << unsigned(lo_index) << std::endl; - - return lo_index; -} - -uint8_t CGpSinkTable::getEntryIndexForSourceId(uint32_t i_source_id) -{ - uint8_t lo_index = GP_SINK_INVALID_ENTRY; - -/* - std::stringstream buf; - buf << "[source_id : "<< std::hex << std::setw(8) << std::setfill('0') << unsigned(i_source_id) << "]"; - clogI << "CGpSinkTable::getEntryIndexForSourceId : " << buf.str() << std::endl; -*/ - - for( unsigned int loop=0; loop255) - { - clogW << "gpd table index overflow\n"; - } - else - { - lo_index = static_cast(loop); - break; - } - } - } - -// clogI << "CGpSinkTable::getEntryIndexForSourceId at index : " << unsigned(lo_index) << std::endl; - - return lo_index; -} diff --git a/src/domain/zigbee-tools/green-power-sink-table.h b/src/domain/zigbee-tools/green-power-sink-table.h deleted file mode 100644 index c9cb8adb..00000000 --- a/src/domain/zigbee-tools/green-power-sink-table.h +++ /dev/null @@ -1,50 +0,0 @@ -/** - * @file green-power-sink-table.h - * - * @brief A green power sink table - */ -#pragma once - -#include -#include -#include "../zbmessage/green-power-sink-table-entry.h" - -#ifdef USE_RARITAN -/**** Start of the official API; no includes below this point! ***************/ -#include -#endif // USE_RARITAN - - -#define GP_SINK_INVALID_ENTRY 0xFF - -class CGpSinkTable -{ -public: - CGpSinkTable(const CGpSinkTable&) = delete; /* No copy construction allowed */ - - CGpSinkTable(); - - /** - * @brief add a green power sink table entry - * - * @return index of entry in sink table, or GP_SINK_INVALID_ENTRY if table is full - */ - uint8_t addEntry( CGpSinkTableEntry i_entry ); - - /** - * @brief obtain entry index according to a gpd source id - * - * @param i_source_id source id of gpd - * - * @return index of sink table entry, GP_SINK_INVALID_ENTRY if not found - */ - uint8_t getEntryIndexForSourceId(uint32_t i_source_id); - -private: - std::vector gpds; - -}; - -#ifdef USE_RARITAN -#include -#endif // USE_RARITAN \ No newline at end of file diff --git a/src/domain/zigbee-tools/green-power-sink.cpp b/src/domain/zigbee-tools/green-power-sink.cpp index e897d304..2c365c06 100644 --- a/src/domain/zigbee-tools/green-power-sink.cpp +++ b/src/domain/zigbee-tools/green-power-sink.cpp @@ -141,25 +141,12 @@ void CGpSink::handleEzspRxMessage( EEzspCmd i_cmd, std::vector i_msg_re // build gpf frame from ezsp rx message CGpFrame gpf = CGpFrame(i_msg_receive); - - // Start DEBUG clogD << "EZSP_GPEP_INCOMING_MESSAGE_HANDLER status : " << CEzspEnum::EEmberStatusToString(l_status) << ", link : " << unsigned(i_msg_receive.at(1)) << ", sequence number : " << unsigned(i_msg_receive.at(2)) << - ", gp address : " << gpf <(i_msg_receive[i]) << " "; - } - clogI << "raw : " << bufDump.str() << std::endl; -*/ - // Stop DEBUG - /** * trame gpf: * - no cryptée : on essaye de la validé en donner la TC link key (zig...009), dans le cas ou il s'agit d'une trame de commissioning diff --git a/src/libezsp.mk.inc b/src/libezsp.mk.inc index beb3332e..c749ba4d 100644 --- a/src/libezsp.mk.inc +++ b/src/libezsp.mk.inc @@ -25,7 +25,6 @@ LIBEZSP_COMMON_SRC = \ $(SRC_DOMAIN_PATH)/zigbee-tools/zigbee-networking.cpp \ $(SRC_DOMAIN_PATH)/zigbee-tools/zigbee-messaging.cpp \ $(SRC_DOMAIN_PATH)/zigbee-tools/green-power-sink.cpp \ - $(SRC_DOMAIN_PATH)/zigbee-tools/green-power-sink-table.cpp \ LIBEZSP_LINUX_SPI_SRC = \ $(SRC_SPI_PATH)/GenericAsyncDataInputObservable.cpp \ From 45f479c36248177d81210abf906a61fade886eca Mon Sep 17 00:00:00 2001 From: Lionel AINS Date: Fri, 22 Nov 2019 14:21:38 +0100 Subject: [PATCH 42/44] Removing use of exceptions due to Raritan framework --- src/example/mainEzspTest.cpp | 31 ++++++++++++++----------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/src/example/mainEzspTest.cpp b/src/example/mainEzspTest.cpp index cbf05f62..722cc7bc 100644 --- a/src/example/mainEzspTest.cpp +++ b/src/example/mainEzspTest.cpp @@ -44,18 +44,20 @@ static void writeUsage(const char* progname, FILE *f) { /** * @brief Convert an ASCII character representing one hexadecimal digit ([0-9a-fA-F]) to its value (0-15) * - * @param hDigit The input printable ASCII character - * @return The value of the hexadecimal digit as a uint8_t nibble (0-15) + * @param[in] hDigit The input printable ASCII character + * @param[out] byte The value of the hexadecimal digit as a uint8_t nibble (0-15) + * @return true if the conversion succeeded **/ -uint8_t hexDigitToNibble(const char hDigit) { +static bool hexDigitToNibble(const char hDigit, uint8_t& byte) { if (hDigit>='a' && hDigit<='f') - return static_cast(hDigit + 10 - 'a'); + byte = static_cast(hDigit + 10 - 'a'); else if (hDigit>='A' && hDigit<='F') - return static_cast(hDigit + 10 - 'A'); + byte = static_cast(hDigit + 10 - 'A'); else if (hDigit>='0' && hDigit<='9') - return static_cast(hDigit - '0'); + byte = static_cast(hDigit - '0'); else - throw std::out_of_range("Invalid character '" + std::string(1, hDigit) + "'"); + return false; + return true; } int main(int argc, char **argv) { @@ -115,22 +117,17 @@ int main(int argc, char **argv) { if (gpDevKeyStr != "") { std::vector argAsBytes; for (unsigned int i = 0; i < gpDevKeyStr.length(); i += 2) { - uint8_t byte; - try { - byte = hexDigitToNibble(gpDevKeyStr[i]) << 4; - } - catch (const std::out_of_range& e) { + uint8_t hiNibble; + if (!hexDigitToNibble(gpDevKeyStr[i], hiNibble)) { clogE << "Invalid character '" << gpDevKeyStr[i] << "' at position " << i+1 << " in key " << gpDevKeyStr << "\n"; /* Note: 1st char is identified by a position=1 for readability */ exit(1); } - try { - byte |= hexDigitToNibble(gpDevKeyStr[i+1]); - } - catch (const std::out_of_range& e) { + uint8_t loNibble; + if (!hexDigitToNibble(gpDevKeyStr[i+1], loNibble)) { clogE << "Invalid character '" << gpDevKeyStr[i+1] << "' at position " << i+2 << " in key " << gpDevKeyStr << "\n"; /* Note: 1st char is identified by a position=1 for readability */ exit(1); } - argAsBytes.push_back(byte); + argAsBytes.push_back(hiNibble << 4 | loNibble); } //for (uint8_t loop=0; loop Date: Fri, 22 Nov 2019 14:42:33 +0100 Subject: [PATCH 43/44] Updating header files list --- src/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Makefile b/src/Makefile index 67b1a3b9..e075c0b9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -25,7 +25,6 @@ libezspincludedir = $(includedir)/include/local/ezsp libezspinclude_HEADERS = \ domain/zigbee-tools/zigbee-networking.h \ -domain/zigbee-tools/green-power-sink-table.h \ domain/zigbee-tools/green-power-sink.h \ domain/zigbee-tools/zigbee-messaging.h \ domain/green-power-observer.h \ From fb5cc33b8b61a664f2e913363d115016ba52e4ea Mon Sep 17 00:00:00 2001 From: Lionel Ains Date: Fri, 22 Nov 2019 14:42:48 +0100 Subject: [PATCH 44/44] Fixing cast warning --- src/example/mainEzspTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/example/mainEzspTest.cpp b/src/example/mainEzspTest.cpp index 722cc7bc..1528c7b1 100644 --- a/src/example/mainEzspTest.cpp +++ b/src/example/mainEzspTest.cpp @@ -127,7 +127,7 @@ int main(int argc, char **argv) { clogE << "Invalid character '" << gpDevKeyStr[i+1] << "' at position " << i+2 << " in key " << gpDevKeyStr << "\n"; /* Note: 1st char is identified by a position=1 for readability */ exit(1); } - argAsBytes.push_back(hiNibble << 4 | loNibble); + argAsBytes.push_back(static_cast(hiNibble << 4) | loNibble); } //for (uint8_t loop=0; loop