[A]add sdk_core.

This commit is contained in:
Livox-SDK
2019-01-18 23:07:03 +08:00
parent e0b8bd9dd2
commit 4b677d5d64
47 changed files with 5922 additions and 0 deletions
+86
View File
@@ -0,0 +1,86 @@
cmake_minimum_required(VERSION 3.0)
set(SDK_LIBRARY ${PROJECT_NAME}_static)
add_library(${SDK_LIBRARY} STATIC "")
find_package(PkgConfig)
pkg_check_modules(APR apr-1)
if (APR_FOUND)
target_include_directories(${SDK_LIBRARY}
PRIVATE
${APR_INCLUDE_DIRS})
target_link_libraries(${SDK_LIBRARY}
PRIVATE
${APR_LIBRARIES})
elseif ()
message("Can't find Apache Runtime Library, please install.")
endif ()
find_package(Boost 1.54 REQUIRED COMPONENTS system)
if (Boost_FOUND AND Boost_VERSION LESS 106900)
target_link_libraries(${SDK_LIBRARY}
PRIVATE
${Boost_LIBRARIES})
endif ()
target_include_directories(${SDK_LIBRARY}
PUBLIC
include
include/third_party/FastCRC
PRIVATE
src)
set_target_properties(${SDK_LIBRARY} PROPERTIES PUBLIC_HEADER "include/livox_def.h;include/livox_sdk.h")
target_compile_options(${SDK_LIBRARY}
PRIVATE $<$<CXX_COMPILER_ID:GNU>:-Wall -Werror -Wno-c++11-long-long>
PRIVATE $<$<CXX_COMPILER_ID:AppleClang>:-Wno-unknown-pragmas -Wall -Werror -Wno-c++11-long-long>
PRIVATE $<$<CXX_COMPILER_ID:Clang>:-Wno-unknown-pragmas -Wall -Werror -Wno-c++11-long-long>)
target_sources(${SDK_LIBRARY}
PRIVATE
src/third_party/FastCRC/FastCRC_tables.hpp
src/third_party/FastCRC/FastCRCsw.cpp
src/base/io_loop.h
src/base/io_loop.cpp
src/base/thread_base.h
src/base/thread_base.cpp
src/base/io_thread.h
src/base/io_thread.cpp
src/base/network_util.h
src/base/network_util.cpp
src/base/logging.h
src/base/noncopyable.h
src/base/util.cpp
src/livox_sdk.cpp
src/device_discovery.h
src/device_discovery.cpp
src/device_manager.h
src/device_manager.cpp
src/comm/comm_port.cpp
src/comm/sdk_protocol.h
src/comm/sdk_protocol.cpp
src/data_handler/data_handler.h
src/data_handler/data_handler.cpp
src/data_handler/hub_data_handler.h
src/data_handler/hub_data_handler.cpp
src/data_handler/lidar_data_handler.h
src/data_handler/lidar_data_handler.cpp
src/command_handler/command_handler.h
src/command_handler/command_handler.cpp
src/command_handler/command_channel.h
src/command_handler/command_channel.cpp
src/command_handler/hub_command_handler.h
src/command_handler/hub_command_handler.cpp
src/command_handler/lidar_command_handler.h
src/command_handler/lidar_command_handler.cpp
src/command_handler/command_impl.cpp
src/command_handler/command_impl.h)
install(TARGETS ${SDK_LIBRARY}
PUBLIC_HEADER DESTINATION include
ARCHIVE DESTINATION lib
LIBRARY DESTINATION lib)
+72
View File
@@ -0,0 +1,72 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef COMM_COMM_PORT_H_
#define COMM_COMM_PORT_H_
#include <stdint.h>
#include "protocol.h"
namespace livox {
const uint32_t kCacheSize = 8192;
const uint32_t kMoveCacheLimit = 1536;
typedef struct {
uint8_t buf[kCacheSize];
uint32_t rd_idx;
uint32_t wr_idx;
uint32_t size;
} PortCache;
class CommPort {
public:
CommPort();
~CommPort();
int32_t Pack(uint8_t *o_buf, uint32_t o_buf_size, uint32_t *o_len, const CommPacket &i_packet);
int32_t ParseCommStream(CommPacket *o_pack);
uint8_t *FetchCacheFreeSpace(uint32_t *o_len);
int32_t UpdateCacheWrIdx(uint32_t used_size);
uint16_t GetAndUpdateSeqNum();
private:
uint32_t GetCacheTailSize();
uint32_t GetValidDataSize();
void UpdateCache(void);
PortCache cache_;
Protocol *protocol_;
uint32_t parse_step_;
uint16_t seq_num_;
};
} // namespace livox
#endif // COMM_COMM_PORT_H_
+82
View File
@@ -0,0 +1,82 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef COMM_PROTOCOL_H_
#define COMM_PROTOCOL_H_
#include <stdint.h>
namespace livox {
typedef struct CommPacket CommPacket;
typedef int (*RequestPackCb)(CommPacket *packet);
typedef enum { kRequestPack, kAckPack, kMsgPack } PacketType;
typedef enum { kLidarSdk, kRsvd1, kProtocolUndef } ProtocolType;
typedef enum { kNoNeed, kNeedAck, kDelayAck } NeedAckType;
typedef enum { kParseSuccess, kParseFail } ParseResult;
typedef struct CommPacket {
uint8_t packet_type;
uint8_t protocol;
uint8_t protocol_version;
uint8_t cmd_set;
uint32_t cmd_code;
uint32_t sender;
uint32_t sub_sender;
uint32_t receiver;
uint32_t sub_receiver;
uint32_t seq_num;
uint8_t *data;
uint16_t data_len;
uint32_t padding;
// RequestPackCb *ack_request_cb;
// uint32_t retry_times;
// uint32_t timeout;
} CommPacket;
class Protocol {
public:
virtual ~Protocol(){};
virtual int32_t ParsePacket(uint8_t *i_buf, uint32_t i_len, CommPacket *o_packet) = 0;
virtual int32_t Pack(uint8_t *o_buf, uint32_t o_buf_size, uint32_t *o_len, const CommPacket &i_packet) = 0;
virtual uint32_t GetPreambleLen() = 0;
virtual uint32_t GetPacketWrapperLen() = 0;
virtual uint32_t GetPacketLen(uint8_t *buf) = 0;
virtual int32_t CheckPreamble(uint8_t *buf) = 0;
virtual int32_t CheckPacket(uint8_t *buf) = 0;
};
} // namespace livox
#endif // COMM_PROTOCOL_H_
+383
View File
@@ -0,0 +1,383 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_DEF_H_
#define LIVOX_DEF_H_
#include <stdint.h>
#define kMaxLidarCount 32
/** Device type. */
typedef enum {
kDeviceTypeHub = 0, /**< Livox Hub. */
kDeviceTypeLidarMid40 = 1, /**< Mid-40. */
kDeviceTypeLidarTele = 2, /**< Tele. */
kDeviceTypeLidarHorizon = 3 /**< Horizon. */
} DeviceType;
/** Lidar state. */
typedef enum {
kLidarStateInit = 0, /**< Initialization state. */
kLidarStateNormal = 1, /**< Normal work state. */
kLidarStatePowerSaving = 2, /**< Power-saving state. */
kLidarStateStandBy = 3, /**< Standby state. */
kLidarStateError = 4, /**< Error state. */
kLidarStateUnknown = 5
} LidarState;
/** Lidar mode. */
typedef enum {
kLidarModeNormal = 1, /**< Normal mode. */
kLidarModePowerSaving = 2, /**< Power-saving mode. */
kLidarModeStandby = 3 /**< Standby mode. */
} LidarMode;
/** Lidar feature. */
typedef enum {
kLidarFeatureNone = 0, /**< No feature. */
kLidarFeatureRainFog = 1 /**< Rain and fog feature. */
} LidarFeature;
/** Function return value definition. */
typedef enum {
kStatusSuccess = 0, /**< Success. */
kStatusFailure = 1, /**< Failure. */
kStatusNotConnected = 2, /**< Requested device is not connected. */
kStatusNotSupported = 3, /**< Operation is not supported on this device. */
kStatusTimeout = 4, /**< Operation timeouts. */
kStatusNotEnoughMemory = 5 /**< No enough memory. */
} ResponseStatus;
/** Device update type, indicating the change of device connection or working state. */
typedef enum {
kEventConnect = 0, /**< Device is connected. */
kEventDisconnect = 1, /**< Device is removed. */
kEventStateChange = 2 /**< Device working state changes or an error occurs. */
} DeviceEvent;
/** Timestamp sync mode define. */
typedef enum {
kTimestampTypeNoSync = 0, /**< No sync signal mode. */
kTimestampTypePtp = 1, /**< 1588v2.0 PTP sync mode. */
kTimestampTypeRsvd = 2, /**< Reserved use. */
kTimestampTypePpsGps = 3, /**< pps+gps sync mode. */
kTimestampTypePps = 4, /**< pps only sync mode. */
kTimestampTypeUnknown = 5 /**< Unknown mode. */
} TimestampType;
#pragma pack(1)
#define kBroadcastCodeSize 16
/** Cartesian coordinate format. */
typedef struct {
int32_t x; /**< X axis, Unit:mm */
int32_t y; /**< Y axis, Unit:mm */
int32_t z; /**< Z axis, Unit:mm */
uint8_t reflectivity; /**< Reflectivity */
} LivoxRawPoint;
/** standard point cloud format */
typedef struct {
float x; /**< X axis, Unit:m */
float y; /**< X axis, Unit:m */
float z; /**< X axis, Unit:m */
uint8_t reflectivity; /**< Reflectivity */
} LivoxPoint;
/** Point cloud packet. */
typedef struct {
uint8_t version; /**< Packet protocol version. */
uint8_t slot; /**< Slot number used for connecting LiDAR. */
uint8_t id; /**< LiDAR id. */
uint8_t rsvd; /**< Reserved. */
uint32_t err_code; /**< Device error status indicator information. */
uint8_t timestamp_type; /**< Timestamp type. */
/** Point cloud coordinate format, 1 for spherical coordinate data, 0 for cartesian coordinate data. */
uint8_t data_type;
uint8_t timestamp[8]; /**< Nanosecond or UTC format timestamp. */
uint8_t data[1]; /**< Point cloud data. */
} LivoxEthPacket;
/** Information of LiDAR work state. */
typedef union {
uint32_t status_code; /**< LiDAR work state status code. */
uint32_t progress; /**< LiDAR work state switching progress. */
} StatusUnion;
/** Information of the connected LiDAR or hub. */
typedef struct {
char broadcast_code[kBroadcastCodeSize]; /**< Device broadcast code, null-terminated string, 15 characters at most. */
uint8_t handle; /**< Device handle. */
uint8_t slot; /**< Slot number used for connecting LiDAR. */
uint8_t id; /**< LiDAR id. */
uint32_t type; /**< Device type, refer to \ref DeviceType. */
uint16_t data_port; /**< Point cloud data UDP port. */
uint16_t cmd_port; /**< Control command UDP port. */
char ip[16]; /**< IP address. */
LidarState state; /**< LiDAR state. */
LidarFeature feature; /**< LiDAR feature. */
StatusUnion status; /** LiDAR work state status. */
} DeviceInfo;
/** The information of broadcast device. */
typedef struct {
char broadcast_code[kBroadcastCodeSize]; /**< Device broadcast code, null-terminated string, 15 characters at most. */
uint8_t dev_type; /**< Device type, refer to \ref DeviceType. */
uint16_t reserved; /**< Reserved. */
} BroadcastDeviceInfo;
/** The information of LiDAR units that are connected to the Livox Hub. */
typedef struct {
char broadcast_code[kBroadcastCodeSize]; /**< Device broadcast code, null-terminated string, 15 characters at most. */
uint8_t dev_type; /**< Device type, refer to \ref DeviceType. */
uint8_t version[4]; /**< Firmware version. */
uint8_t slot; /**< Slot number used for connecting LiDAR units. */
uint8_t id; /**< Device id. */
} ConnectedLidarInfo;
/** LiDAR mode configuration information. */
typedef struct {
char broadcast_code[kBroadcastCodeSize]; /**< Device broadcast code, null-terminated string, 15 characters at most. */
uint8_t state; /**< LiDAR state. */
} LidarModeRequestItem;
typedef struct {
uint8_t ret_code; /**< Return code. */
char broadcast_code[kBroadcastCodeSize]; /**< Device broadcast code. */
} ReturnCode;
typedef struct {
char broadcast_code[kBroadcastCodeSize]; /**< Device broadcast code. */
} DeviceBroadcastCode;
typedef struct {
char broadcast_code[kBroadcastCodeSize]; /**< Device broadcast code. */
uint8_t feature; /**< Close or open the rain and fog feature. */
} RainFogSuppressRequestItem;
/** LiDAR configuration information. */
typedef struct {
char broadcast_code[kBroadcastCodeSize]; /**< Device broadcast code. */
float roll; /**< Roll angle, unit: degree. */
float pitch; /**< Pitch angle, unit: degree. */
float yaw; /**< Yaw angle, unit: degree. */
int32_t x; /**< X translation, unit: mm. */
int32_t y; /**< Y translation, unit: mm. */
int32_t z; /**< Z translation, unit: mm. */
} ExtrinsicParameterRequestItem;
/** LiDAR extrinsic parameters. */
typedef struct {
uint8_t ret_code; /**< Return code. */
char broadcast_code[kBroadcastCodeSize]; /**< Broadcast code. */
float roll; /**< Roll angle, unit: degree. */
float pitch; /**< Pitch angle, unit: degree. */
float yaw; /**< Yaw angle, unit: degree. */
int32_t x; /**< X translation, unit: mm. */
int32_t y; /**< Y translation, unit: mm. */
int32_t z; /**< Z translation, unit: mm. */
} ExtrinsicParameterResponseItem;
typedef struct {
char broadcast_code[kBroadcastCodeSize]; /**< Broadcast code. */
uint8_t state; /**< LiDAR state. */
uint8_t feature; /**< LiDAR feature. */
StatusUnion error_union; /** LiDAR work state. */
} LidarStateItem;
/**
* The request body for the command of handshake.
*/
typedef struct {
uint32_t ip_addr; /**< IP address of the device. */
uint16_t data_port; /**< UDP port of the data connection. */
uint16_t cmd_port; /**< UDP port of the command connection. */
} HandshakeRequest;
/**
* The response body of querying device information.
*/
typedef struct {
uint8_t ret_code; /**< Return code. */
uint8_t firmware_version[4]; /**< Firmware version. */
} DeviceInformationResponse;
/**
* The response body of getting device error status.
*/
typedef struct {
uint32_t error_code; /**< Error code. */
} ErrorMessage;
/**
* The request body of the command for setting device's IP mode.
*/
typedef struct {
uint8_t ip_mode; /**< IP address mode: 0 for dynamic IP address, 1 for static IP address. */
uint32_t ip_addr; /**< IP address. */
} SetDeviceIPModeRequest;
/**
* The response body of getting device's IP mode.
*/
typedef struct {
uint8_t ret_code; /**< Return code. */
uint8_t ip_mode; /**< IP address mode: 0 for dynamic IP address, 1 for static IP address. */
uint32_t ip_addr; /**< IP address. */
} GetDeviceIPModeResponse;
/**
* The body of heartbeat response.
*/
typedef struct {
uint8_t ret_code; /**< Return code. */
uint8_t state; /**< Working state. */
uint8_t feature; /**< LiDAR feature. */
StatusUnion error_union; /**< LiDAR work state. */
} HeartbeatResponse;
/**
* The request body for the command of setting LiDAR's parameters.
*/
typedef struct {
float roll; /**< Roll angle, unit: degree. */
float pitch; /**< Pitch angle, unit: degree. */
float yaw; /**< Yaw angle, unit: degree. */
int32_t x; /**< X translation, unit: mm. */
int32_t y; /**< Y translation, unit: mm. */
int32_t z; /**< Z translation, unit: mm. */
} LidarSetExtrinsicParameterRequest;
/**
* The response body of getting LiDAR's parameters.
*/
typedef struct {
uint8_t ret_code;
float roll; /**< Roll angle, unit: degree. */
float pitch; /**< Pitch angle, unit: degree. */
float yaw; /**< Yaw angle, unit: degree. */
int32_t x; /**< X translation, unit: mm. */
int32_t y; /**< Y translation, unit: mm. */
int32_t z; /**< Z translation, unit: mm. */
} LidarGetExtrinsicParameterResponse;
/**
* The response body of querying the information of LiDAR units connected to the Livox Hub.
*/
typedef struct {
uint8_t ret_code; /**< Return code from device. */
uint8_t count; /**< Count of device_info_list. */
ConnectedLidarInfo device_info_list[1]; /**< Connected lidars information. */
} HubQueryLidarInformationResponse;
/**
* The request body of setting LiDAR units working mode.
*/
typedef struct {
uint8_t count; /**< Number of LiDAR units to set. */
LidarModeRequestItem config_list[1]; /**< LiDAR mode configuration list. */
} HubSetModeRequest;
/**
* The response of setting LiDAR units working mode.
*/
typedef struct {
uint8_t ret_code; /**< Return code from device. */
uint8_t count; /**< Count of ret_state_list. */
ReturnCode ret_state_list[1]; /**< Return status list. */
} HubSetModeResponse;
/**
* The request body of toggling the power supply of the slot.
*/
typedef struct {
uint8_t slot; /**< Slot of the hub. */
uint8_t state; /**< Status of toggling the power supply. */
} HubControlSlotPowerRequest;
/**
* The request body of setting the Livox Hub's parameters.
*/
typedef struct {
uint8_t count; /**< Count of cfg_param_list. */
ExtrinsicParameterRequestItem parameter_list[1]; /**< Configuration parameter list. */
} HubSetExtrinsicParameterRequest;
/**
* The response body of setting the Livox Hub's parameters.
*/
typedef struct {
uint8_t ret_code; /**< Return code. */
uint8_t count; /**< Count of ret_code_list. */
ReturnCode ret_code_list[1]; /**< Return code */
} HubSetExtrinsicParameterResponse;
/**
* The request body of getting the Livox Hub's parameters.
*/
typedef struct {
uint8_t count; /**< Count of code_list. */
DeviceBroadcastCode code_list[1]; /**< Broadcast code list. */
} HubGetExtrinsicParameterRequest;
/**
* The response body of getting the Livox Hub's parameters.
*/
typedef struct {
uint8_t ret_code; /**< Return code. */
uint8_t count; /**< Number of LiDAR units connected to the Livox Hub. */
ExtrinsicParameterResponseItem parameter_list[1]; /**< Postion parameters of connected LiDAR unit(s). */
} HubGetExtrinsicParameterResponse;
/**
* The response body of getting sub LiDAR's state.
*/
typedef struct {
uint8_t ret_code; /**< Return code. */
uint8_t count; /**< Number of LiDAR connected to the Livox Hub. */
LidarStateItem state_list[1]; /**< Device information of connected LiDAR units. */
} HubQueryLidarStatusResponse;
/**
* The request body of toggling the LiDAR units rain and fog mode.
*/
typedef struct {
uint8_t count; /**< Number of LiDAR units connected to the Livox Hub. */
RainFogSuppressRequestItem lidar_cfg_list[1]; /**< Command data of connected LiDAR units. */
} HubRainFogSuppressRequest;
/**
* The response body of toggling the LiDAR units rain and fog mode.
*/
typedef struct {
uint8_t ret_code; /**< Return code. */
uint8_t count; /**< Count of ret_state_list. */
ReturnCode ret_state_list[1]; /**< Return code */
} HubRainFogSuppressResponse;
#pragma pack()
#endif // LIVOX_DEF_H_
+488
View File
@@ -0,0 +1,488 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_SDK_H_
#define LIVOX_SDK_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdbool.h>
#include <stdint.h>
#include "livox_def.h"
/**
* Initialize the SDK.
* @return true if successfully initialized, otherwise false.
*/
bool Init();
/**
* Start the device scanning routine which runs on a separate thread.
* @return true if successfully started, otherwise false.
*/
bool Start();
/**
* Uninitialize the SDK.
*/
void Uninit();
/**
* @c SetBroadcastCallback response callback function.
* @param info information of the broadcast device, becomes invalid after the function returns.
*/
typedef void (*DeviceBroadcastCallback)(const BroadcastDeviceInfo *info);
/**
* Set the callback of listening device broadcast message. When broadcast message is received from Livox Hub/LiDAR, cb
* is called.
* @param cb callback for device broadcast.
*/
void SetBroadcastCallback(DeviceBroadcastCallback cb);
/**
* @c SetDeviceStateUpdateCallback response callback function.
* @param device information of the connected device.
* @param type the update type that indicates connection/disconnection of the device or change of working state.
*/
typedef void (*DeviceStateUpdateCallback)(const DeviceInfo *device, DeviceEvent type);
/**
* @brief Add a callback for device connection or working state changing event.
* @note Livox SDK supports two hardware connection modes. 1: Directly connecting to the LiDAR device; 2. Connecting to
* the LiDAR device(s) via the Livox Hub. In the first mode, connection/disconnection of every LiDAR unit is reported by
* this callback. In the second mode, only connection/disconnection of the Livox Hub is reported by this callback. If
* you want to get information of the LiDAR unit(s) connected to hub, see \ref HubQueryLidarInformation.
* @note 3 conditions can trigger this callback:
* 1. Connection and disconnection of device.
* 2. A change of device working state.
* 3. An error occurs.
* @param cb callback for device connection/disconnection.
*/
void SetDeviceStateUpdateCallback(DeviceStateUpdateCallback cb);
/**
* Add a broadcast code to the connecting list and only devices with broadcast code in this list will be connected. The
* broadcast code is unique for every device.
* @param broadcast_code device's broadcast code.
* @param handle device handle. For Livox Hub, the handle is always 31; for LiDAR units connected to the Livox Hub,
* the corresponding handle is (slot-1)*3+id-1.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t AddHubToConnect(const char *broadcast_code, uint8_t *handle);
/**
* Add a broadcast code to the connecting list and only devices with broadcast code in this list will be connected. The
* broadcast code is unique for every device.
* @param broadcast_code device's broadcast code.
* @param handle device handle. The handle is the same as the order calling AddLidarToConnect starting from 0.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t AddLidarToConnect(const char *broadcast_code, uint8_t *handle);
/**
* Get all connected devices' information.
* @param devices list of connected devices' information.
* @param size number of devices connected.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t GetConnectedDevices(DeviceInfo *devices, uint8_t *size);
/**
* Function type of callback that queries device's information.
* @param status kStatusSuccess on successful return, kStatusTimeout on timeout, see \ref ResponseStatus for other
* error code.
* @param handle device handle.
* @param response response from the device.
* @param client_data user data associated with the command.
*/
typedef void (*DeviceInformationCallback)(uint8_t status,
uint8_t handle,
DeviceInformationResponse *response,
void *client_data);
/**
* Command to query device's information.
* @param handle device handle.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t QueryDeviceInformation(uint8_t handle, DeviceInformationCallback cb, void *client_data);
/**
* Callback function for receiving point cloud data.
* @param handle device handle.
* @param data device's data.
* @param data_num number of points in data.
*/
typedef void (*DataCallback)(uint8_t handle, LivoxEthPacket *data, uint32_t data_num);
/**
* Set the callback to receive point cloud data. Only one callback is supported for a specific device. Set the point
* cloud data callback before beginning sampling.
* @param cb callback to receive point cloud data.
*/
void SetDataCallback(uint8_t handle, DataCallback cb);
/**
* Function type of callback with 1 byte of response.
* @param status kStatusSuccess on successful return, kStatusTimeout on timeout, see \ref ResponseStatus for other
* error code.
* @param handle device handle.
* @param response response from the device.
* @param client_data user data associated with the command.
*/
typedef void (*CommonCommandCallback)(uint8_t status, uint8_t handle, uint8_t response, void *client_data);
/**
* Start hub sampling.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t HubStartSampling(CommonCommandCallback cb, void *client_data);
/**
* Stop the Livox Hub's sampling.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t HubStopSampling(CommonCommandCallback cb, void *client_data);
/**
* Get the LiDAR unit handle used in the Livox Hub data callback function from slot and id.
* @param slot Livox Hub's slot.
* @param id Livox Hub's id.
* @return LiDAR unit handle.
*/
uint8_t HubGetLidarHandle(uint8_t slot, uint8_t id);
/**
* Command to change point cloud coordinate system to cartesian coordinate.
* @param handle device handle.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t SetCartesianCoordinate(uint8_t handle, CommonCommandCallback cb, void *client_data);
/**
* Change point cloud coordinate system to spherical coordinate.
* @param handle device handle.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t SetSphericalCoordinate(uint8_t handle, CommonCommandCallback cb, void *client_data);
/**
* Callback of the error status message.
* @param handle device handle.
* @param response response from the device.
*/
typedef void (*ErrorMessageCallback)(uint8_t handle, ErrorMessage *message);
/**
* Add error status callback for the device.
* @param handle device handle.
* @param cb callback for the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t SetErrorMessageCallback(uint8_t handle, ErrorMessageCallback cb);
/**
* Set device's IP mode.
* @param handle device handle.
* @param req request sent to device.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t SetStaticDynamicIP(uint8_t handle,
SetDeviceIPModeRequest *req,
CommonCommandCallback cb,
void *client_data);
/**
* Callback function that gets device's IP information.
* @param status kStatusSuccess on successful return, kStatusTimeout on timeout, see \ref ResponseStatus for other
* error code.
* @param handle device handle.
* @param response response from the device.
* @param client_data user data associated with the command.
*/
typedef void (*GetDeviceIPInformationCallback)(uint8_t status,
uint8_t handle,
GetDeviceIPModeResponse *response,
void *client_data);
/**
* Get device's IP mode.
* @param handle device handle.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t GetDeviceIPInformation(uint8_t handle, GetDeviceIPInformationCallback cb, void *client_data);
/**
* @c HubQueryLidarInformation response callback function.
* @param status kStatusSuccess on successful return, kStatusTimeout on timeout, see \ref ResponseStatus for other
* error code.
* @param handle device handle.
* @param response response from the device.
* @param client_data user data associated with the command.
*/
typedef void (*HubQueryLidarInformationCallback)(uint8_t status,
uint8_t handle,
HubQueryLidarInformationResponse *response,
void *client_data);
/**
* Query the information of LiDARs connected to the hub.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t HubQueryLidarInformation(HubQueryLidarInformationCallback cb, void *client_data);
/**
* @c HubSetMode response callback function.
* @param status kStatusSuccess on successful return, kStatusTimeout on timeout, see \ref ResponseStatus for other
* error code.
* @param handle device handle.
* @param response response from the device.
* @param client_data user data associated with the command.
*/
typedef void (*HubSetModeCallback)(uint8_t status, uint8_t handle, HubSetModeResponse *response, void *client_data);
/**
* Set the mode of LiDAR unit connected to the Livox Hub.
* @param req mode configuration of LiDAR units.
* @param length length of req.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t HubSetMode(HubSetModeRequest *req, uint16_t length, HubSetModeCallback cb, void *client_data);
/**
* @c HubQueryLidarStatus response callback function.
* @param status kStatusSuccess on successful return, kStatusTimeout on timeout, see \ref ResponseStatus for other
* error code.
* @param handle device handle.
* @param response response from the device.
* @param client_data user data associated with the command.
*/
typedef void (*HubQueryLidarStatusCallback)(uint8_t status, uint8_t handle, HubQueryLidarStatusResponse *response, void *client_data);
/**
* Get the state of LiDAR units connected to the Livox Hub.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t HubQueryLidarStatus(HubQueryLidarStatusCallback cb, void *client_data);
/**
* Toggle the power supply of designated slots.
* @param req request whether to enable or disable the power of designated slots.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t HubControlSlotPower(HubControlSlotPowerRequest *req, CommonCommandCallback cb, void *client_data);
/**
* @c HubSetExtrinsicParameter response callback function.
* @param status kStatusSuccess on successful return, kStatusTimeout on timeout, see \ref ResponseStatus for other
* error code.
* @param handle device handle.
* @param response response from the device.
* @param client_data user data associated with the command.
*/
typedef void (*HubSetExtrinsicParameterCallback)(uint8_t status,
uint8_t handle,
HubSetExtrinsicParameterResponse *response,
void *client_data);
/**
* Set extrinsic parameters of LiDAR units connected to the Livox Hub.
* @param req the parameters to write.
* @param length the request's length.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t HubSetExtrinsicParameter(HubSetExtrinsicParameterRequest *req,
uint16_t length,
HubSetExtrinsicParameterCallback cb,
void *client_data);
/**
* @c HubGetExtrinsicParameter response callback function.
* @param status kStatusSuccess on successful return, kStatusTimeout on timeout, see \ref ResponseStatus for other
* error code.
* @param handle device handle.
* @param response response from the device.
* @param client_data user data associated with the command.
*/
typedef void (*HubGetExtrinsicParameterCallback)(uint8_t status,
uint8_t handle,
HubGetExtrinsicParameterResponse *response,
void *client_data);
/**
* Get extrinsic parameters of LiDAR units connected to the Livox Hub.
* @param req the LiDAR units broadcast code list.
* @param length the request's length.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t HubGetExtrinsicParameter(HubGetExtrinsicParameterRequest *req,
uint16_t length,
HubGetExtrinsicParameterCallback cb,
void *client_data);
/**
* Turn on or off the calculation of extrinsic parameters.
* @param enable the request whether enable or disable calculating the extrinsic parameters.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t HubExtrinsicParameterCalculation(bool enable, CommonCommandCallback cb, void *client_data);
/**
* @c HubRainFogSuppress response callback function.
* @param status kStatusSuccess on successful return, kStatusTimeout on timeout, see \ref ResponseStatus for other
* error code.
* @param handle device handle.
* @param response response from the device.
* @param client_data user data associated with the command.
*/
typedef void (*HubRainFogSuppressCallback)(uint8_t status,
uint8_t handle,
HubRainFogSuppressResponse *response,
void *client_data);
/**
* Toggling the rain and fog mode for lidars connected to the hub.
* @param req the request whether open or close the rain and fog mode.
* @param length the request's length.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t HubRainFogSuppress(HubRainFogSuppressRequest *req,
uint16_t length,
HubRainFogSuppressCallback cb,
void *client_data);
/**
* Start LiDAR sampling.
* @param handle device handle.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t LidarStartSampling(uint8_t handle, CommonCommandCallback cb, void *client_data);
/**
* Stop LiDAR sampling.
* @param handle device handle.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t LidarStopSampling(uint8_t handle, CommonCommandCallback cb, void *client_data);
/**
* Set LiDAR mode.
* @note Successful callback function status only means LiDAR successfully starting the changing process of mode.
* You need to observe the actually change of mode in DeviceStateUpdateCallback function.
* @param handle device handle.
* @param mode the mode to change.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t LidarSetMode(uint8_t handle, LidarMode mode, CommonCommandCallback cb, void *client_data);
/**
* Set LiDAR extrinsic parameters.
* @param handle device handle.
* @param param the parameters to write.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t LidarSetExtrinsicParameter(uint8_t handle,
LidarSetExtrinsicParameterRequest *req,
CommonCommandCallback cb,
void *client_data);
/**
* @c LidarGetExtrinsicParameter response callback function.
* @param status kStatusSuccess on successful return, kStatusTimeout on timeout, see \ref ResponseStatus for other
* error code.
* @param handle device handle.
* @param response response from the device.
* @param client_data user data associated with the command.
*/
typedef void (*LidarGetExtrinsicParameterCallback)(uint8_t status,
uint8_t handle,
LidarGetExtrinsicParameterResponse *response,
void *client_data);
/**
* Get LiDAR extrinsic parameters.
* @param handle device handle.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t LidarGetExtrinsicParameter(uint8_t handle, LidarGetExtrinsicParameterCallback cb, void *client_data);
/**
* Enable and disable the rain/fog suppression.
* @param handle device handle.
* @param cb callback for the command.
* @param client_data user data associated with the command.
* @return kStatusSuccess on successful return, see \ref ResponseStatus for other error code.
*/
uint8_t LidarRainFogSuppress(uint8_t handle, bool enable, CommonCommandCallback cb, void *client_data);
#ifdef __cplusplus
}
#endif
#endif // LIVOX_SDK_H_
+79
View File
@@ -0,0 +1,79 @@
/* FastCRC library code is placed under the MIT license
* Copyright (c) 2014,2015 Frank Bosing
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
// Teensy 3.0, Teensy 3.1:
// See K20P64M72SF1RM.pdf (Kinetis), Pages 638 - 641 for documentation of CRC Device
// See KINETIS_4N30D.pdf for Errata (Errata ID 2776)
//
// So, ALL HW-calculations are done as 32 bit.
//
//
//
// Thanks to:
// - Catalogue of parametrised CRC algorithms, CRC RevEng
// http://reveng.sourceforge.net/crc-catalogue/
//
// - Danjel McGougan (CRC-Table-Generator)
//
//
// modify from FastCRC library @ 2018/11/20
//
#ifndef FASTCRC_FASTCRC_H_
#define FASTCRC_FASTCRC_H_
#include <stdint.h>
// ================= 16-BIT CRC ===================
class FastCRC16 {
public:
FastCRC16(uint16_t seed);
// change function name from mcrf4xx_upd to mcrf4xx
uint16_t mcrf4xx_calc(const uint8_t *data,const uint16_t datalen); // Equivalent to _crc_ccitt_update() in crc16.h from avr_libc
private:
uint16_t seed_;
};
// ================= 32-BIT CRC ===================
class FastCRC32 {
public:
FastCRC32(uint32_t seed);
// change function name from crc32_upd to crc32
uint32_t crc32_calc(const uint8_t *data, uint16_t len); // Call for subsequent calculations with previous seed
private:
uint32_t seed_;
};
#endif // FASTCRC_FASTCRC_H_
+245
View File
@@ -0,0 +1,245 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_COMMAND_CALLBACK_H
#define LIVOX_COMMAND_CALLBACK_H
#include <boost/function.hpp>
#include <boost/smart_ptr.hpp>
#include "livox_sdk.h"
namespace livox {
class CommandCallback {
public:
virtual ~CommandCallback() {}
virtual void operator()(uint8_t handle, void *data) = 0;
};
template <class T, class ResponseType>
class MemberFunctionCallback : public CommandCallback {
public:
typedef void (T::*MemFn)(uint8_t status, uint8_t handle, ResponseType *data);
MemberFunctionCallback(T *cls, MemFn func) : this_(cls), func_(func) {}
void operator()(uint8_t handle, void *data) {
if (this_) {
(this_->*func_)((data == NULL) ? kStatusTimeout : kStatusSuccess, handle, static_cast<ResponseType *>(data));
}
}
private:
T *this_;
MemFn func_;
};
template <class T>
class MemberFunctionCallback<T, uint8_t> : public CommandCallback {
public:
typedef void (T::*MemFn)(uint8_t status, uint8_t handle, uint8_t response);
MemberFunctionCallback(T *cls, MemFn func) : this_(cls), func_(func) {}
void operator()(uint8_t handle, void *data) {
if (this_) {
(this_->*func_)((data == NULL) ? kStatusTimeout : kStatusSuccess,
handle,
static_cast<uint8_t>(reinterpret_cast<uintptr_t>(data)));
}
}
private:
T *this_;
MemFn func_;
};
template <class T, class ResponseType>
boost::shared_ptr<CommandCallback> MakeCommandCallback(T *cls,
typename MemberFunctionCallback<T, ResponseType>::MemFn func) {
boost::shared_ptr<CommandCallback> cb(new MemberFunctionCallback<T, ResponseType>(cls, func));
return cb;
}
template <class T>
class FunctionStatusCallback : public CommandCallback {
public:
typedef void (*Fn)(uint8_t status, uint8_t handle, T *data, void *client_data);
public:
FunctionStatusCallback(Fn func, void *client_data) : func_(func), client_data_(client_data) {}
void operator()(uint8_t handle, void *data) {
if (func_) {
(*func_)((data == NULL) ? kStatusTimeout : kStatusSuccess, handle, static_cast<T *>(data), client_data_);
}
}
private:
Fn func_;
void *client_data_;
};
template <>
class FunctionStatusCallback<uint8_t> : public CommandCallback {
public:
typedef void (*Fn)(uint8_t status, uint8_t handle, uint8_t data, void *client_data);
public:
FunctionStatusCallback(Fn func, void *client_data) : func_(func), client_data_(client_data) {}
void operator()(uint8_t handle, void *data) {
if (func_) {
if (data == NULL) {
(*func_)(kStatusTimeout, handle, 0, client_data_);
} else {
(*func_)(kStatusSuccess, handle, *(uint8_t *)data, client_data_);
}
}
}
private:
Fn func_;
void *client_data_;
};
template <class T>
boost::shared_ptr<CommandCallback> MakeCommandCallback(typename FunctionStatusCallback<T>::Fn func, void *client_data) {
boost::shared_ptr<CommandCallback> cb(new FunctionStatusCallback<T>(func, client_data));
return cb;
}
template <class T>
class MessageCallback : public CommandCallback {
public:
typedef void (*Fn)(uint8_t handle, T *data);
public:
MessageCallback(const Fn &func) : func_(func) {}
void operator()(uint8_t handle, void *data) {
if (func_) {
(*func_)(handle, static_cast<T *>(data));
}
}
private:
Fn func_;
};
template <class ResponseType>
class BoostFunctionMessageCallback : public CommandCallback {
public:
typedef boost::function<void(uint8_t, ResponseType *)> Fn;
public:
BoostFunctionMessageCallback(const Fn &func) : func_(func) {}
void operator()(uint8_t handle, void *data) {
if (func_) {
func_(handle, static_cast<ResponseType *>(data));
}
}
private:
Fn func_;
};
template <class T>
boost::shared_ptr<CommandCallback> MakeMessageCallback(typename MessageCallback<T>::Fn func) {
boost::shared_ptr<CommandCallback> cb(new MessageCallback<T>(func));
return cb;
}
template <class T>
boost::shared_ptr<CommandCallback> MakeMessageCallback(typename BoostFunctionMessageCallback<T>::Fn func) {
boost::shared_ptr<CommandCallback> cb(new BoostFunctionMessageCallback<T>(func));
return cb;
}
template <class T, class ResponseType>
class MemberMessageCallback : public CommandCallback {
public:
typedef void (T::*MemFn)(uint8_t handle, ResponseType *data);
MemberMessageCallback(T *cls, MemFn func) : this_(cls), func_(func) {}
void operator()(uint8_t handle, void *data) {
if (this_) {
(this_->*func_)(handle, (ResponseType *)data);
}
}
private:
T *this_;
MemFn func_;
};
template <class T, class ResponseType>
boost::shared_ptr<CommandCallback> MakeMemberMessageCallback(
T *_this,
typename MemberMessageCallback<T, ResponseType>::MemFn func) {
boost::shared_ptr<CommandCallback> cb(new MemberMessageCallback<T, ResponseType>(_this, func));
return cb;
}
template <class ResponseType>
class BoostFunctionCallback : public CommandCallback {
public:
typedef boost::function<void(uint8_t, uint8_t, ResponseType *)> Fn;
BoostFunctionCallback(const Fn &func) : func_(func) {}
void operator()(uint8_t handle, void *data) {
if (func_) {
if (data == NULL) {
func_(kStatusTimeout, handle, NULL);
} else {
func_(kStatusSuccess, handle, (ResponseType *)data);
}
}
}
private:
Fn func_;
};
template <>
class BoostFunctionCallback<uint8_t> : public CommandCallback {
public:
typedef boost::function<void(uint8_t, uint8_t, uint8_t)> Fn;
BoostFunctionCallback(const Fn &func) : func_(func) {}
void operator()(uint8_t handle, void *data) {
if (func_) {
if (data == NULL) {
func_(kStatusTimeout, handle, 0);
} else {
func_(kStatusSuccess, handle, static_cast<uint8_t>(reinterpret_cast<uintptr_t>(data)));
}
}
}
private:
Fn func_;
};
template <class ResponseType>
boost::shared_ptr<CommandCallback> MakeCommandCallback(const typename BoostFunctionCallback<ResponseType>::Fn &func) {
boost::shared_ptr<CommandCallback> cb(new BoostFunctionCallback<ResponseType>(func));
return cb;
}
} // namespace livox
#endif // LIVOX_COMMAND_CALLBACK_H
+182
View File
@@ -0,0 +1,182 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "io_loop.h"
#include <boost/bind.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/thread/locks.hpp>
#include <iostream>
#include "logging.h"
using boost::lock_guard;
using boost::mutex;
using std::vector;
namespace livox {
bool IOLoop::Init() {
if (mem_pool_ == NULL) {
return false;
}
apr_status_t rv =
apr_pollset_create(&pollset_, kMaxPollCount, mem_pool_, APR_POLLSET_THREADSAFE | APR_POLLSET_WAKEABLE);
if (rv != APR_SUCCESS) {
LOG_ERROR << PrintAPRStatus(rv) << std::endl;
return false;
}
return true;
}
void IOLoop::Uninit() {
if (pollset_) {
apr_pollset_destroy(pollset_);
pollset_ = NULL;
}
for (DelegatesType::const_iterator ite = delegates_.begin(); ite != delegates_.end(); ++ite) {
ClientData *data = ite->second;
if (data) {
delete data;
}
}
delegates_.clear();
mem_pool_ = NULL;
}
void IOLoop::AddDelegate(apr_socket_t *sock, IOLoop::IOLoopDelegate *delegate, void *data) {
PostTask(boost::bind(&IOLoop::AddDelegateAsync, this, sock, delegate, data));
}
void IOLoop::RemoveDelegate(apr_socket_t *sock, IOLoopDelegate *) {
PostTask(boost::bind(&IOLoop::RemoveDelegateAsync, this, sock));
}
void IOLoop::Loop() {
apr_int32_t num = 0;
const apr_pollfd_t *ret_pfd = NULL;
apr_status_t rv = apr_pollset_poll(pollset_, apr_time_from_msec(50), &num, &ret_pfd);
if (rv == APR_SUCCESS) {
for (int i = 0; i < num; i++) {
ClientData *data = static_cast<ClientData *>(ret_pfd[i].client_data);
;
if (data) {
IOLoopDelegate *delegate = data->first;
if (delegate) {
delegate->OnData(ret_pfd->desc.s, data->second);
}
}
}
}
if (enable_wake_ && APR_STATUS_IS_EINTR(rv)) {
DelegatesType delegates = delegates_;
for (DelegatesType::const_iterator ite = delegates.begin(); ite != delegates.end(); ++ite) {
ClientData *data = ite->second;
if (data) {
IOLoopDelegate *delegate = data->first;
if (delegate) {
delegate->OnWake();
}
}
}
}
if (enable_timer_) {
apr_time_t t = apr_time_now();
if (last_timeout_ == 0 || t - last_timeout_ > apr_time_from_msec(50)) {
last_timeout_ = t;
// copy delegates_ in case delegate is removed in callback.
DelegatesType delegates = delegates_;
for (DelegatesType::const_iterator ite = delegates.begin(); ite != delegates.end(); ++ite) {
ClientData *data = ite->second;
if (data) {
IOLoopDelegate *delegate = data->first;
if (delegate) {
delegate->OnTimer(t);
}
}
}
}
}
vector<IOLoopTask> tasks;
{
lock_guard<mutex> lock(mutex_);
tasks.swap(pending_tasks_);
}
for (vector<IOLoopTask>::iterator ite = tasks.begin(); ite != tasks.end(); ++ite) {
IOLoopTask &task = *ite;
task();
}
if (rv != APR_SUCCESS && !APR_STATUS_IS_TIMEUP(rv) && !APR_STATUS_IS_EINTR(rv)) {
LOG_ERROR << PrintAPRStatus(rv) << std::endl;
}
}
bool IOLoop::Wakeup() {
apr_status_t rv = apr_pollset_wakeup(pollset_);
if (rv != APR_SUCCESS) {
LOG_ERROR << PrintAPRStatus(rv) << std::endl;
return false;
}
return true;
}
void IOLoop::PostTask(const IOLoopTask &task) {
{
lock_guard<mutex> lock(mutex_);
pending_tasks_.push_back(task);
}
Wakeup();
}
void IOLoop::AddDelegateAsync(apr_socket_t *sock, IOLoop::IOLoopDelegate *delegate, void *data) {
ClientData *p = new ClientData(delegate, data);
apr_pollfd_t pfd = {mem_pool_, APR_POLL_SOCKET, APR_POLLIN, 0, {NULL}, p};
pfd.desc.s = sock;
apr_pollset_add(pollset_, &pfd);
delegates_[sock] = p;
}
void IOLoop::RemoveDelegateAsync(apr_socket_t *sock) {
apr_pollfd_t pfd = {mem_pool_, APR_POLL_SOCKET, 0, 0, {NULL}, NULL};
pfd.desc.s = sock;
apr_pollset_remove(pollset_, &pfd);
DelegatesType::iterator ite = delegates_.find(sock);
if (ite != delegates_.end()) {
ClientData *p = ite->second;
if (p) {
delete p;
}
delegates_.erase(ite);
}
}
} // namespace livox
+87
View File
@@ -0,0 +1,87 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_IO_LOOP_H_
#define LIVOX_IO_LOOP_H_
#include <boost/function.hpp>
#include <boost/thread/mutex.hpp>
#include <boost/unordered_map.hpp>
#include <utility>
#include <vector>
#include "apr_general.h"
#include "apr_network_io.h"
#include "apr_poll.h"
#include "apr_thread_proc.h"
#include "command_callback.h"
#include "noncopyable.h"
#include "thread_base.h"
#include "util.h"
namespace livox {
class IOLoop : public noncopyable {
public:
class IOLoopDelegate {
public:
virtual void OnData(apr_socket_t *, void *) {}
virtual void OnTimer(apr_time_t) {}
virtual void OnWake() {}
};
typedef boost::function<void(void)> IOLoopTask;
public:
explicit IOLoop(apr_pool_t *mem_pool, bool enable_timer = true, bool enable_wake = true)
: pollset_(NULL), mem_pool_(mem_pool), last_timeout_(0), enable_timer_(enable_timer), enable_wake_(enable_wake){};
bool Init();
void Uninit();
void AddDelegate(apr_socket_t *sock, IOLoopDelegate *delegate, void *data = NULL);
void RemoveDelegate(apr_socket_t *sock, IOLoopDelegate *delegate);
void Loop();
bool Wakeup();
void PostTask(const IOLoopTask &task);
private:
void AddDelegateAsync(apr_socket_t *sock, IOLoopDelegate *delegate, void *data);
void RemoveDelegateAsync(apr_socket_t *sock);
private:
static const apr_uint32_t kMaxPollCount = 48;
typedef std::pair<IOLoopDelegate *, void *> ClientData;
typedef boost::unordered_map<apr_socket_t *, ClientData *> DelegatesType;
DelegatesType delegates_;
apr_pollset_t *pollset_;
apr_pool_t *mem_pool_;
apr_time_t last_timeout_;
boost::mutex mutex_;
bool enable_timer_;
bool enable_wake_;
std::vector<IOLoopTask> pending_tasks_;
};
} // namespace livox
#endif // LIVOX_IO_LOOP_H_
+60
View File
@@ -0,0 +1,60 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "io_thread.h"
#include "apr_pools.h"
namespace livox {
void IOThread::Join() {
ThreadBase::Join();
}
void IOThread::ThreadFunc() {
if (loop_ == NULL) {
return;
}
while (!IsQuit()) {
loop_->Loop();
}
}
bool IOThread::Init(bool enable_timer, bool enable_wake) {
if (!ThreadBase::Init()) {
return false;
}
loop_.reset(new IOLoop(pool_, enable_timer, enable_wake));
return loop_->Init();
}
void IOThread::Uninit() {
if (loop_) {
loop_->Uninit();
loop_.reset(NULL);
}
ThreadBase::Uninit();
}
} // namespace livox
+47
View File
@@ -0,0 +1,47 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_IO_THREAD_H_
#define LIVOX_IO_THREAD_H_
#include <boost/smart_ptr.hpp>
#include "io_loop.h"
#include "thread_base.h"
namespace livox {
class IOThread : public ThreadBase {
public:
IOThread() : loop_(NULL) {}
bool Init(bool enable_timer = true, bool enable_wake = true);
void Join();
void Uninit();
IOLoop *loop() { return loop_.get(); }
void ThreadFunc();
private:
boost::scoped_ptr<IOLoop> loop_;
};
} // namespace livox
#endif // LIVOX_IO_THREAD_H_
+39
View File
@@ -0,0 +1,39 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_LOGGING_H_
#define LIVOX_LOGGING_H_
#include <iomanip>
#include <iostream>
#define __FILENAME__ (strrchr(__FILE__, '/') ? (strrchr(__FILE__, '/') + 1) : __FILE__)
#define LOG_TRACE std::cout << "TRACE " << __FILENAME__ << ":" << __LINE__ << " " << __FUNCTION__ << " "
#define LOG_DEBUG std::cout << "DEBUG " << __FILENAME__ << ":" << __LINE__ << " " << __FUNCTION__ << " "
#define LOG_INFO std::cout << "INFO " << __FILENAME__ << ":" << __LINE__ << " " << __FUNCTION__ << " "
#define LOG_WARN std::cout << "WARN " << __FILENAME__ << ":" << __LINE__ << " " << __FUNCTION__ << " "
#define LOG_ERROR std::cout << "ERROR " << __FILENAME__ << ":" << __LINE__ << " " << __FUNCTION__ << " "
#define LOG_FATAL std::cout << "FATAL " << __FILENAME__ << ":" << __LINE__ << " " << __FUNCTION__ << " "
#endif // LIVOX_LOGGING_H_
+90
View File
@@ -0,0 +1,90 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "network_util.h"
#include <ifaddrs.h>
namespace livox {
namespace util {
apr_socket_t *CreateBindSocket(uint16_t port, apr_pool_t *mem_pool, bool nonblock) {
apr_sockaddr_t *sa = NULL;
apr_socket_t *s = NULL;
apr_status_t rv = APR_SUCCESS;
rv = apr_sockaddr_info_get(&sa, NULL, APR_INET, port, 0, mem_pool);
if (rv != APR_SUCCESS) {
return NULL;
}
rv = apr_socket_create(&s, sa->family, SOCK_DGRAM, APR_PROTO_UDP, mem_pool);
if (rv != APR_SUCCESS) {
return NULL;
}
rv = apr_socket_bind(s, sa);
if (rv != APR_SUCCESS) {
apr_socket_close(s);
s = NULL;
return NULL;
}
if (nonblock) {
apr_socket_opt_set(s, APR_SO_NONBLOCK, 1);
apr_socket_timeout_set(s, 0);
}
return s;
}
bool FindLocalIP(const struct sockaddr_in &client_addr, uint32_t &local_ip) {
struct ifaddrs *if_addrs = NULL, *addrs = NULL;
if (getifaddrs(&if_addrs) == -1) {
return false;
}
addrs = if_addrs;
bool found = false;
while (if_addrs != NULL) {
if ((if_addrs->ifa_addr != NULL) && (if_addrs->ifa_addr->sa_family == AF_INET)) // check it is IP4
{
// is a connected IP4 Address
struct sockaddr_in *ifu_localaddr = (struct sockaddr_in *)if_addrs->ifa_addr;
struct sockaddr_in *ifu_netmask = (struct sockaddr_in *)if_addrs->ifa_netmask;
if (ifu_localaddr->sin_addr.s_addr != htonl(INADDR_ANY)) {
if ((ifu_localaddr->sin_addr.s_addr & ifu_netmask->sin_addr.s_addr) ==
(client_addr.sin_addr.s_addr & ifu_netmask->sin_addr.s_addr)) {
local_ip = ifu_localaddr->sin_addr.s_addr;
found = true;
break;
}
}
}
if_addrs = if_addrs->ifa_next;
}
if (addrs) {
freeifaddrs(addrs);
}
return found;
}
} // namespace util
} // namespace livox
+38
View File
@@ -0,0 +1,38 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_NETWORK_UTIL_H_
#define LIVOX_NETWORK_UTIL_H_
#include <apr_general.h>
#include <apr_network_io.h>
namespace livox {
namespace util {
apr_socket_t *CreateBindSocket(uint16_t port, apr_pool_t *mem_pool, bool nonblock = true);
bool FindLocalIP(const struct sockaddr_in &client_addr, uint32_t &local_ip);
} // namespace util
} // namespace livox
#endif // LIVOX_NETWORK_UTIL_H_
+40
View File
@@ -0,0 +1,40 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_NONCOPYABLE_H_
#define LIVOX_NONCOPYABLE_H_
namespace livox {
class noncopyable {
protected:
noncopyable() {}
~noncopyable() {}
private:
noncopyable(const noncopyable &);
noncopyable &operator=(const noncopyable &);
};
} // namespace livox
#endif // LIVOX_NONCOPYABLE_H_
+71
View File
@@ -0,0 +1,71 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "thread_base.h"
namespace livox {
static void *APR_THREAD_FUNC ClassThreadHelperFunc(apr_thread_t *thd, void *data) {
ThreadBase *caller = static_cast<ThreadBase *>(data);
if (caller == NULL) {
return NULL;
}
caller->ThreadFunc();
apr_thread_exit(thd, APR_SUCCESS);
return NULL;
}
ThreadBase::ThreadBase() : thread_(NULL), quit_(false), pool_(NULL) {}
bool ThreadBase::Start() {
quit_ = false;
apr_threadattr_t *thread_attr = NULL;
apr_status_t rv = APR_SUCCESS;
rv = apr_threadattr_create(&thread_attr, pool_);
if (rv != APR_SUCCESS) {
return false;
}
rv = apr_thread_create(&thread_, thread_attr, ClassThreadHelperFunc, this, pool_);
return rv == APR_SUCCESS;
}
void ThreadBase::Join() {
apr_status_t rv = APR_SUCCESS;
if (thread_) {
apr_thread_join(&rv, thread_);
thread_ = NULL;
}
}
bool ThreadBase::Init() {
return apr_pool_create(&pool_, NULL) == APR_SUCCESS;
}
void ThreadBase::Uninit() {
if (pool_) {
apr_pool_destroy(pool_);
pool_ = NULL;
}
}
} // namespace livox
+54
View File
@@ -0,0 +1,54 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_THREAD_BASE_H_
#define LIVOX_THREAD_BASE_H_
#include <apr_general.h>
#include <apr_thread_proc.h>
#include <boost/atomic/atomic.hpp>
#include "noncopyable.h"
namespace livox {
class ThreadBase : public noncopyable {
public:
ThreadBase();
virtual ~ThreadBase() {}
virtual void ThreadFunc() = 0;
bool Init();
virtual void Uninit();
virtual bool Start();
virtual void Join();
void Quit() { quit_ = true; }
bool IsQuit() { return quit_; }
protected:
apr_thread_t *thread_;
boost::atomic_bool quit_;
apr_pool_t *pool_;
};
} // namespace livox
#endif // LIVOX_THREAD_BASE_H_
+52
View File
@@ -0,0 +1,52 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "util.h"
#include <stdio.h>
#include <stdlib.h>
using std::string;
namespace livox {
string PrintAPRStatus(apr_status_t s) {
char buf[128];
apr_strerror(s, buf, sizeof(buf));
return buf;
}
string PrintAPRTime(apr_time_t t) {
char cbuf[45 + 1];
apr_size_t sz = 45;
apr_time_exp_t xt;
apr_time_exp_gmt(&xt, t);
int milli = t % 1000;
apr_strftime(cbuf, &sz, 45, " %T.", &xt);
string s(cbuf);
char buffer[33];
sprintf(buffer, "%d", milli);
s += buffer;
return s;
}
} // namespace livox
+37
View File
@@ -0,0 +1,37 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_UTIL_H_
#define LIVOX_UTIL_H_
#include <string>
#include "apr_general.h"
#include "apr_time.h"
namespace livox {
std::string PrintAPRStatus(apr_status_t s);
std::string PrintAPRTime(apr_time_t t);
} // namespace livox
#endif // LIVOX_UTIL_H_
+164
View File
@@ -0,0 +1,164 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "comm/comm_port.h"
#include <stdio.h>
#include <string.h>
#include <iostream>
#include "sdk_protocol.h"
namespace livox {
const uint32_t kSearchPacketPreamble = 0;
const uint32_t kGetPacketData = 1;
CommPort::CommPort() {
protocol_ = new SdkProtocol(0x4c49, 0x564f580a);
cache_.wr_idx = 0;
cache_.rd_idx = 0;
cache_.size = kCacheSize;
parse_step_ = kSearchPacketPreamble;
seq_num_ = 0;
}
CommPort::~CommPort() {
if (protocol_) {
delete protocol_;
}
}
uint8_t *CommPort::FetchCacheFreeSpace(uint32_t *o_len) {
UpdateCache();
if (cache_.wr_idx < cache_.size) {
*o_len = cache_.size - cache_.wr_idx;
return &cache_.buf[cache_.wr_idx];
} else {
*o_len = 0;
return NULL;
}
}
int32_t CommPort::UpdateCacheWrIdx(uint32_t used_size) {
if ((cache_.wr_idx + used_size) < cache_.size) {
cache_.wr_idx += used_size;
return 0;
} else {
return -1;
}
}
uint32_t CommPort::GetCacheTailSize() {
if (cache_.wr_idx < cache_.size) {
return cache_.size - cache_.wr_idx;
} else {
return 0;
}
}
uint32_t CommPort::GetValidDataSize() {
if (cache_.wr_idx > cache_.rd_idx) {
return cache_.wr_idx - cache_.rd_idx;
} else {
return 0;
}
}
void CommPort::UpdateCache(void) {
if (GetCacheTailSize() < kMoveCacheLimit) { // move unused data to cache head
uint32_t valid_data_size = GetValidDataSize();
if (valid_data_size) {
memmove(cache_.buf, &cache_.buf[cache_.rd_idx], valid_data_size);
cache_.rd_idx = 0;
cache_.wr_idx = valid_data_size;
} else if (cache_.rd_idx) {
cache_.rd_idx = 0;
cache_.wr_idx = 0;
}
}
}
int32_t CommPort::Pack(uint8_t *o_buf, uint32_t o_buf_size, uint32_t *o_len, const CommPacket &i_packet) {
return protocol_->Pack(o_buf, o_buf_size, o_len, i_packet);
}
int32_t CommPort::ParseCommStream(CommPacket *o_pack) {
#define CUR_PACK_LEN (protocol_->GetPacketLen(&cache_.buf[cache_.rd_idx]))
#define CUR_CACHE_POS (&cache_.buf[cache_.rd_idx])
while (GetValidDataSize() > protocol_->GetPreambleLen()) {
// printf("unpack step : %d %d %d\r\n", parse_step_, cache_.wr_idx, cache_.rd_idx);
if (kSearchPacketPreamble == parse_step_) {
if (!protocol_->CheckPreamble(CUR_CACHE_POS)) {
parse_step_ = kGetPacketData;
} else {
++cache_.rd_idx;
}
} else if (kGetPacketData == parse_step_) {
if (GetValidDataSize() >= CUR_PACK_LEN && CUR_PACK_LEN) {
parse_step_ = kSearchPacketPreamble;
if (!protocol_->CheckPacket(CUR_CACHE_POS)) {
int32_t ret = protocol_->ParsePacket(CUR_CACHE_POS, GetValidDataSize(), o_pack);
cache_.rd_idx += CUR_PACK_LEN;
if (kParseSuccess == ret) {
return ret;
}
} else {
cache_.rd_idx += protocol_->GetPreambleLen();
}
} else {
if (CUR_PACK_LEN > cache_.size) { // always > cache_.size,
cache_.rd_idx = 0;
cache_.wr_idx = 0;
parse_step_ = kSearchPacketPreamble;
}
break;
}
} else {
parse_step_ = kSearchPacketPreamble;
}
}
return kParseFail;
}
uint16_t CommPort::GetAndUpdateSeqNum() {
// add lock here for thread safe
uint16_t seq = seq_num_;
seq_num_++;
return seq;
}
// only for pack function test use
// uint8_t test_buf[1024];
// uint32_t o_len = 0;
// comm_port_->Pack(test_buf, sizeof(test_buf), &o_len, packet);
// for (uint32_t print_i = 0; print_i < o_len; print_i++) {
// printf("%.2x_", test_buf[print_i]);
//}
// printf("\r\n");
} // namespace livox
+128
View File
@@ -0,0 +1,128 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "sdk_protocol.h"
#include <stdio.h>
#include <string.h>
namespace livox {
const uint8_t kSdkProtocolSof = 0xAA;
const uint32_t kSdkPacketCrcSize = 4; // crc32
const uint32_t kSdkPacketPreambleCrcSize = 2; // crc16
SdkProtocol::SdkProtocol(uint16_t seed16, uint32_t seed32) : crc16_(seed16), crc32_(seed32) {}
SdkProtocol::~SdkProtocol() {}
int32_t SdkProtocol::Pack(uint8_t *o_buf, uint32_t o_buf_size, uint32_t *o_len, const CommPacket &i_packet) {
SdkPacket *sdk_packet = (SdkPacket *)o_buf;
if (kLidarSdk != i_packet.protocol) {
return -1;
}
sdk_packet->sof = kSdkProtocolSof;
sdk_packet->length = i_packet.data_len + GetPacketWrapperLen();
if (sdk_packet->length > o_buf_size) {
return -1;
}
sdk_packet->version = kSdkVer0;
sdk_packet->packet_type = i_packet.packet_type;
sdk_packet->seq_num = i_packet.seq_num & 0xFFFF;
sdk_packet->preamble_crc = crc16_.mcrf4xx_calc(o_buf, GetPreambleLen() - kSdkPacketPreambleCrcSize);
sdk_packet->cmd_set = i_packet.cmd_set;
sdk_packet->cmd_id = i_packet.cmd_code;
memcpy(sdk_packet->data, i_packet.data, i_packet.data_len);
uint32_t crc = crc32_.crc32_calc(o_buf, sdk_packet->length - kSdkPacketCrcSize);
o_buf[sdk_packet->length - 4] = crc & 0xFF;
o_buf[sdk_packet->length - 3] = (crc >> 8) & 0xFF;
o_buf[sdk_packet->length - 2] = (crc >> 16) & 0xFF;
o_buf[sdk_packet->length - 1] = (crc >> 24) & 0xFF;
*o_len = sdk_packet->length;
return 0;
}
int32_t SdkProtocol::ParsePacket(uint8_t *i_buf, uint32_t i_len, CommPacket *o_packet) {
SdkPacket *sdk_packet = (SdkPacket *)i_buf;
if (i_len < GetPacketWrapperLen()) {
return -1; // packet lenth error
}
memset((void *)o_packet, 0, sizeof(CommPacket));
o_packet->packet_type = sdk_packet->packet_type;
o_packet->protocol = kLidarSdk;
o_packet->protocol_version = sdk_packet->version;
o_packet->seq_num = sdk_packet->seq_num;
o_packet->cmd_set = sdk_packet->cmd_set;
o_packet->cmd_code = sdk_packet->cmd_id;
o_packet->data_len = sdk_packet->length - GetPacketWrapperLen();
o_packet->data = sdk_packet->data;
return 0;
}
uint32_t SdkProtocol::GetPreambleLen() {
return sizeof(SdkPreamble);
}
uint32_t SdkProtocol::GetPacketWrapperLen() {
return sizeof(SdkPacket) - 1 + kSdkPacketCrcSize;
}
uint32_t SdkProtocol::GetPacketLen(uint8_t *buf) {
SdkPreamble *preamble = (SdkPreamble *)buf;
return preamble->length;
}
int32_t SdkProtocol::CheckPreamble(uint8_t *buf) {
SdkPreamble *preamble = (SdkPreamble *)buf;
if ((preamble->sof == kSdkProtocolSof) && (crc16_.mcrf4xx_calc(buf, GetPreambleLen()) == 0)) {
return 0;
} else {
return -1;
}
}
int32_t SdkProtocol::CheckPacket(uint8_t *buf) {
SdkPacket *sdk_packet = (SdkPacket *)buf;
uint32_t crc = ((uint32_t)(buf[sdk_packet->length - 4])) | (((uint32_t)(buf[sdk_packet->length - 3])) << 8) |
(((uint32_t)(buf[sdk_packet->length - 2])) << 16) | (((uint32_t)(buf[sdk_packet->length - 1])) << 24);
if (crc32_.crc32_calc(buf, sdk_packet->length - kSdkPacketCrcSize) == crc) {
return 0;
} else {
return -1;
}
}
} // namespace livox
+84
View File
@@ -0,0 +1,84 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_SDK_PROTOCOL_H_
#define LIVOX_SDK_PROTOCOL_H_
#include <stdint.h>
#include "../include/comm/protocol.h"
#include "../include/third_party/FastCRC/FastCRC.h"
namespace livox {
typedef enum { kSdkVerNone, kSdkVer0, kSdkVer1 } SdkVersion;
#pragma pack(1)
typedef struct {
uint8_t sof;
uint8_t version;
uint16_t length;
uint8_t packet_type;
uint16_t seq_num;
uint16_t preamble_crc;
} SdkPreamble;
typedef struct {
uint8_t sof;
uint8_t version;
uint16_t length;
uint8_t packet_type;
uint16_t seq_num;
uint16_t preamble_crc;
uint8_t cmd_set;
uint8_t cmd_id;
uint8_t data[1];
} SdkPacket;
#pragma pack()
class SdkProtocol : public Protocol {
public:
SdkProtocol(uint16_t seed16, uint32_t seed32);
~SdkProtocol();
int32_t ParsePacket(uint8_t *i_buf, uint32_t i_len, CommPacket *o_packet);
int32_t Pack(uint8_t *o_buf, uint32_t o_buf_size, uint32_t *o_len, const CommPacket &i_packet);
uint32_t GetPreambleLen();
uint32_t GetPacketWrapperLen();
uint32_t GetPacketLen(uint8_t *buf);
int32_t CheckPreamble(uint8_t *buf);
int32_t CheckPacket(uint8_t *buf);
private:
FastCRC16 crc16_;
FastCRC32 crc32_;
};
} // namespace livox
#endif // LIVOX_SDK_PROTOCOL_H_
@@ -0,0 +1,242 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "command_channel.h"
#include <boost/bind.hpp>
#include "base/logging.h"
#include "base/network_util.h"
#include "command_impl.h"
#include "device_manager.h"
#include "livox_def.h"
using boost::atomic_uint16_t;
using boost::bind;
using std::list;
using std::make_pair;
using std::map;
using std::pair;
using std::string;
namespace livox {
CommandChannel::CommandChannel(apr_port_t port,
uint8_t handle,
const string &remote_ip,
CommandChannelDelegate *cb,
apr_pool_t *pool)
: handle_(handle),
port_(port),
sock_(NULL),
mem_pool_(pool),
loop_(NULL),
callback_(cb),
comm_port_(new CommPort),
heartbeat_time_(0),
remote_ip_(remote_ip),
last_heartbeat_(0) {}
bool CommandChannel::Bind(IOLoop *loop) {
if (loop == NULL) {
return false;
}
loop_ = loop;
sock_ = util::CreateBindSocket(port_, mem_pool_);
if (sock_ == NULL) {
return false;
}
loop_->AddDelegate(sock_, this);
return true;
}
void CommandChannel::OnData(apr_socket_t *, void *) {
apr_sockaddr_t addr;
uint32_t buf_size = 0;
uint8_t *cache_buf = comm_port_->FetchCacheFreeSpace(&buf_size);
apr_size_t size = buf_size;
apr_status_t rv = apr_socket_recvfrom(&addr, sock_, 0, reinterpret_cast<char *>(cache_buf), &size);
comm_port_->UpdateCacheWrIdx(size);
if (rv != APR_SUCCESS) {
LOG_ERROR << PrintAPRStatus(rv) << std::endl;
return;
}
CommPacket packet;
memset(&packet, 0, sizeof(packet));
while ((kParseSuccess == comm_port_->ParseCommStream(&packet))) {
if (packet.packet_type == kCommandTypeAck) {
uint16_t seq = packet.seq_num;
if (commands_.find(seq) != commands_.end()) {
Command command = commands_[seq].first;
command.packet = packet;
if (callback_) {
callback_->OnCommand(handle_, command);
}
commands_.erase(seq);
} else if (packet.cmd_set == kCommandSetGeneral && packet.cmd_code == kCommandIDGeneralHeartbeat) {
OnHeartbeatAck(packet);
if (callback_) {
callback_->OnHeartbeatStateUpdate(handle_, *(reinterpret_cast<HeartbeatResponse *>(packet.data)));
}
}
} else if (packet.packet_type == kCommandTypeMsg) {
if (callback_) {
Command command;
command.packet = packet;
callback_->OnCommand(handle_, command);
}
}
}
}
void CommandChannel::SendAsync(const Command &command) {
Command cmd = DeepCopy(command);
if (loop_) {
loop_->PostTask(bind(&CommandChannel::Send, this, cmd));
}
}
void CommandChannel::OnTimer(apr_time_t now) {
list<Command> timeout_commands;
map<uint16_t, pair<Command, apr_time_t> >::iterator ite = commands_.begin();
while (ite != commands_.end()) {
pair<Command, apr_time_t> &command_pair = ite->second;
if (now > command_pair.second) {
timeout_commands.push_back(command_pair.first);
commands_.erase(ite++);
} else {
++ite;
}
}
for (list<Command>::iterator ite = timeout_commands.begin(); ite != timeout_commands.end(); ++ite) {
LOG_WARN << PrintAPRTime(apr_time_now()) << " Command Timeout: Set " << (uint16_t)ite->packet.cmd_set << " Id "
<< ite->packet.cmd_code << " Seq " << ite->packet.seq_num << std::endl;
if (callback_) {
ite->packet.packet_type = kCommandTypeAck;
callback_->OnCommand(handle_, *ite);
}
}
if ((last_heartbeat_ != 0) && (now - last_heartbeat_ > apr_time_from_sec(3))) {
DeviceDisconnect(handle_);
} else {
HeartBeat(now);
}
}
void CommandChannel::Uninit() {
if (sock_) {
loop_->RemoveDelegate(sock_, this);
loop_ = NULL;
apr_socket_close(sock_);
sock_ = NULL;
}
callback_ = NULL;
if (comm_port_) {
comm_port_.reset(NULL);
}
commands_.clear();
last_heartbeat_ = 0;
heartbeat_time_ = 0;
remote_ip_ = "";
}
void CommandChannel::HeartBeat(apr_time_t t) {
if (heartbeat_time_ == 0 || (t - heartbeat_time_) > apr_time_from_msec(kHeartbeatTimer)) {
heartbeat_time_ = t;
Command command(handle_,
kCommandTypeCmd,
kCommandSetGeneral,
kCommandIDGeneralHeartbeat,
GenerateSeq(),
NULL,
0,
0,
boost::shared_ptr<CommandCallback>());
SendInternal(command);
}
}
void CommandChannel::SendInternal(const Command &command) {
apr_pool_t *subpool = NULL;
apr_pool_create(&subpool, mem_pool_);
uint8_t *buf = (uint8_t *)apr_palloc(subpool, kMaxCommandBufferSize);
uint32_t size = 0;
comm_port_->Pack(buf, kMaxCommandBufferSize, &size, command.packet);
apr_size_t apr_size = size;
apr_status_t rv = APR_SUCCESS;
apr_sockaddr_t *sa = NULL;
rv = apr_sockaddr_info_get(&sa, remote_ip_.c_str(), APR_INET, 65000, 0, subpool);
if (rv == APR_SUCCESS) {
rv = apr_socket_sendto(sock_, sa, 0, (const char *)buf, &apr_size);
}
apr_pool_destroy(subpool);
}
uint16_t CommandChannel::GenerateSeq() {
static atomic_uint16_t seq(1);
uint16_t value = seq.load();
uint16_t desired = 0;
do {
if (value == UINT16_MAX) {
desired = 1;
} else {
desired = value + 1;
}
} while (!seq.compare_exchange_weak(value, desired));
return desired;
}
Command CommandChannel::DeepCopy(const Command &cmd) {
Command result_cmd(cmd);
if (result_cmd.packet.data != NULL) {
result_cmd.packet.data = new uint8_t[result_cmd.packet.data_len];
memcpy(result_cmd.packet.data, cmd.packet.data, result_cmd.packet.data_len);
}
return result_cmd;
}
void CommandChannel::OnHeartbeatAck(const CommPacket &) {
last_heartbeat_ = apr_time_now();
}
void CommandChannel::DeviceDisconnect(uint8_t handle) {
DeviceRemove(handle);
}
void CommandChannel::Send(const Command &command) {
SendInternal(command);
commands_[command.packet.seq_num] = make_pair(command, apr_time_now() + apr_time_from_msec(command.time_out));
Command &cmd = commands_[command.packet.seq_num].first;
if (cmd.packet.data != NULL) {
delete cmd.packet.data;
cmd.packet.data = NULL;
cmd.packet.data_len = 0;
}
}
} // namespace livox
@@ -0,0 +1,126 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_COMMAND_CHANNEL_H_
#define LIVOX_COMMAND_CHANNEL_H_
#include <boost/smart_ptr.hpp>
#include <list>
#include <string>
#include "apr_network_io.h"
#include "base/io_loop.h"
#include "comm/comm_port.h"
namespace livox {
typedef struct TagCommand {
uint8_t handle;
CommPacket packet;
boost::shared_ptr<CommandCallback> cb;
uint32_t time_out;
TagCommand() : packet(), time_out(0) {}
TagCommand(uint8_t _handle,
uint8_t _cmd_type,
uint8_t _cmd_set,
uint8_t _cmd_code,
uint16_t _seq_num,
uint8_t *data,
uint16_t length,
uint32_t _time_out,
const boost::shared_ptr<CommandCallback> &_cb)
: handle(_handle), packet(), cb(_cb) {
packet.packet_type = _cmd_type;
packet.cmd_set = _cmd_set;
packet.cmd_code = _cmd_code;
packet.seq_num = _seq_num;
packet.data = data;
packet.data_len = length;
time_out = _time_out;
}
} Command;
class CommandChannelDelegate {
public:
virtual void OnCommand(uint8_t handle, const Command &command) = 0;
virtual void OnHeartbeatStateUpdate(uint8_t handle, const HeartbeatResponse &state) = 0;
};
/**
* CommandChannel implements the sending/receiving commands with a specific device.
*/
class CommandChannel : public IOLoop::IOLoopDelegate {
public:
CommandChannel(apr_port_t port,
uint8_t handle,
const std::string &remote_ip,
CommandChannelDelegate *cb,
apr_pool_t *pool);
virtual ~CommandChannel() { Uninit(); }
/** Uninitialize CommandChannel. */
void Uninit();
/**
* Bind a CommandChannel with a IOLoop.
* @param loop the IOLoop to bind.
* @return true on successfully.
*/
bool Bind(IOLoop *loop);
/**
* Send a command asynchronously.
* @param command the command to send.
*/
void SendAsync(const Command &command);
void OnData(apr_socket_t *, void *);
void OnTimer(apr_time_t now);
static uint16_t GenerateSeq();
private:
void Send(const Command &cmd);
void HeartBeat(apr_time_t t);
void SendInternal(const Command &command);
Command DeepCopy(const Command &cmd);
void OnHeartbeatAck(const CommPacket &packet);
void DeviceDisconnect(uint8_t handle);
private:
static const int kHeartbeatTimer = 800;
uint8_t handle_;
apr_port_t port_;
apr_socket_t *sock_;
apr_pool_t *mem_pool_;
IOLoop *loop_;
CommandChannelDelegate *callback_;
std::map<uint16_t, std::pair<Command, apr_time_t> > commands_;
boost::scoped_ptr<CommPort> comm_port_;
apr_time_t heartbeat_time_;
std::string remote_ip_;
apr_time_t last_heartbeat_;
};
} // namespace livox
#endif // LIVOX_COMMAND_CHANNEL_H_
@@ -0,0 +1,179 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "command_handler.h"
#include <boost/thread/lock_guard.hpp>
#include <boost/thread/locks.hpp>
#include "command_impl.h"
#include "device_manager.h"
#include "hub_command_handler.h"
#include "lidar_command_handler.h"
using boost::lock_guard;
using boost::mutex;
using boost::shared_ptr;
using std::list;
using std::make_pair;
using std::multimap;
using std::pair;
namespace livox {
CommandHandler &command_handler() {
static CommandHandler handler;
return handler;
}
uint16_t GetCommandTimeout(uint8_t command_set, uint8_t command_id) {
switch (command_set) {
case kCommandSetGeneral:
assert(command_id < sizeof(GeneralCommandTimeout));
return GeneralCommandTimeout[command_id];
case kCommandSetLidar:
assert(command_id < sizeof(LidarCommandTimeout));
return LidarCommandTimeout[command_id];
case kCommandSetHub:
assert(command_id < sizeof(HubCommandTimeout));
return HubCommandTimeout[command_id];
}
return KDefaultTimeOut;
}
bool CommandHandler::AddDevice(const DeviceInfo &info) {
if (impl_ == NULL) {
DeviceMode mode = static_cast<DeviceMode>(device_manager().device_mode());
if (mode == kDeviceModeHub) {
impl_.reset(new HubCommandHandlerImpl(this, mem_pool_, loop_));
} else if (mode == kDeviceModeLidar) {
impl_.reset(new LidarCommandHandlerImpl(this, mem_pool_, loop_));
}
}
if (impl_ == NULL) {
return false;
}
return impl_->AddDevice(info);
}
bool CommandHandler::Init(IOLoop *loop) {
apr_status_t rv = apr_pool_create(&mem_pool_, NULL);
if (rv != APR_SUCCESS) {
return false;
}
loop_ = loop;
return true;
}
void CommandHandler::Uninit() {
loop_ = NULL;
if (impl_) {
impl_.reset(NULL);
}
if (mem_pool_) {
apr_pool_destroy(mem_pool_);
mem_pool_ = NULL;
}
}
void CommandHandler::OnCommand(uint8_t handle, const Command &command) {
if (command.packet.packet_type == kCommandTypeAck) {
OnCommandAck(handle, command);
} else if (command.packet.packet_type == kCommandTypeMsg) {
OnCommandMsg(handle, command);
}
}
bool CommandHandler::SendCommand(uint8_t handle,
uint8_t command_set,
uint8_t command_id,
uint8_t *data,
uint16_t length,
const shared_ptr<CommandCallback> &cb) {
if (impl_ == NULL) {
return false;
}
Command cmd(handle,
kCommandTypeCmd,
command_set,
command_id,
CommandChannel::GenerateSeq(),
data,
length,
GetCommandTimeout(command_set, command_id),
cb);
bool result = impl_->SendCommand(handle, cmd);
return result;
}
bool CommandHandler::RegisterPush(uint8_t handle,
uint8_t command_set,
uint8_t command_id,
const shared_ptr<CommandCallback> &cb) {
lock_guard<mutex> lock(mutex_);
Command req(handle, kCommandTypeMsg, command_set, command_id, 0, NULL, 0, 0, cb);
message_registers_.insert(make_pair(MakeKey(command_set, command_id), req));
return true;
}
void CommandHandler::OnCommandAck(uint8_t handle, const Command &command) {
if (command.cb != NULL) {
(*command.cb)(handle, command.packet.data);
}
}
void CommandHandler::OnCommandMsg(uint8_t handle, const Command &command) {
list<Command> commands;
{
lock_guard<mutex> lock(mutex_);
pair<multimap<uint16_t, Command>::iterator, multimap<uint16_t, Command>::iterator> ret;
ret = message_registers_.equal_range(MakeKey(command.packet.cmd_set, command.packet.cmd_code));
for (multimap<uint16_t, Command>::iterator ite = ret.first; ite != ret.second; ++ite) {
if (ite->second.handle == handle) {
commands.push_back(ite->second);
}
}
}
for (list<Command>::iterator ite = commands.begin(); ite != commands.end(); ++ite) {
if (ite->cb) {
(*ite->cb)(handle, command.packet.data);
}
}
}
void CommandHandler::RemoveDevice(uint8_t handle) {
if (impl_) {
impl_->RemoveDevice(handle);
};
}
void CommandHandler::OnHeartbeatStateUpdate(uint8_t handle, const HeartbeatResponse &state) {
device_manager().UpdateDeviceState(handle, state);
}
} // namespace livox
@@ -0,0 +1,109 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_COMMAND_HANDLER_H_
#define LIVOX_COMMAND_HANDLER_H_
#include <boost/smart_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include "base/command_callback.h"
#include "base/util.h"
#include "command_channel.h"
#include "device_discovery.h"
#include "livox_sdk.h"
namespace livox {
class CommandHandlerImpl;
class CommandHandler : public noncopyable {
public:
explicit CommandHandler() : mem_pool_(NULL), loop_(NULL) {}
bool Init(IOLoop *loop);
void Uninit();
bool AddDevice(const DeviceInfo &info);
void RemoveDevice(uint8_t handle);
bool SendCommand(uint8_t handle,
uint8_t command_set,
uint8_t command_id,
uint8_t *data,
uint16_t length,
const boost::shared_ptr<CommandCallback> &cb);
bool RegisterPush(uint8_t handle,
uint8_t command_set,
uint8_t command_id,
const boost::shared_ptr<CommandCallback> &cb);
void OnCommand(uint8_t handle, const Command &command);
void OnHeartbeatStateUpdate(uint8_t handle, const HeartbeatResponse &state);
private:
inline uint16_t MakeKey(uint8_t command_set, uint8_t command_id) { return (command_set << 8) | command_id; }
void OnCommandAck(uint8_t handle, const Command &command);
void OnCommandMsg(uint8_t handle, const Command &command);
private:
std::multimap<uint16_t, Command> message_registers_;
apr_pool_t *mem_pool_;
boost::scoped_ptr<CommandHandlerImpl> impl_;
boost::mutex mutex_;
IOLoop *loop_;
};
class CommandHandlerImpl : public CommandChannelDelegate {
public:
CommandHandlerImpl(CommandHandler *handler) : handler_(handler) {}
virtual ~CommandHandlerImpl() { Uninit(); }
virtual void Uninit(){};
virtual bool AddDevice(const DeviceInfo &info) = 0;
virtual bool RemoveDevice(uint8_t handle) = 0;
virtual bool SendCommand(uint8_t handle, const Command &command) = 0;
virtual void OnCommand(uint8_t handle, const Command &command) {
if (handler_) {
handler_->OnCommand(handle, command);
}
}
void OnHeartbeatStateUpdate(uint8_t handle, const HeartbeatResponse &state) {
if (handler_) {
handler_->OnHeartbeatStateUpdate(handle, state);
}
}
private:
CommandHandler *handler_;
};
CommandHandler &command_handler();
} // namespace livox
#endif // LIVOX_COMMAND_HANDLER_H_
@@ -0,0 +1,352 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include <livox_sdk.h>
#include "command_handler.h"
#include "command_impl.h"
#include "data_handler/data_handler.h"
#include "device_manager.h"
#include "livox_def.h"
#include "livox_sdk.h"
using std::pair;
using std::vector;
using namespace livox;
void SetDeviceStateUpdateCallback(DeviceStateUpdateCallback cb) {
device_manager().SetDeviceConnectedCallback(cb);
}
void SetBroadcastCallback(DeviceBroadcastCallback cb) {
device_manager().SetDeviceBroadcastCallback(cb);
}
uint8_t AddHubToConnect(const char *broadcast_code, uint8_t *handle) {
bool result = device_manager().AddListeningDevice(broadcast_code, kDeviceModeHub, *handle);
if (result) {
return kStatusSuccess;
} else {
return kStatusFailure;
}
}
uint8_t AddLidarToConnect(const char *broadcast_code, uint8_t *handle) {
bool result = device_manager().AddListeningDevice(broadcast_code, kDeviceModeLidar, *handle);
if (result) {
return kStatusSuccess;
} else {
return kStatusFailure;
}
}
uint8_t GetConnectedDevices(DeviceInfo *devices, uint8_t *size) {
if (devices == NULL || size == NULL) {
return kStatusFailure;
}
vector<DeviceInfo> device;
device_manager().GetConnectedDevices(device);
uint16_t final_size = (*size >= device.size()) ? device.size() : *size;
for (int i = 0; i < final_size; i++) {
devices[i] = device[i];
}
*size = final_size;
return kStatusSuccess;
}
void SetDataCallback(uint8_t handle, DataCallback cb) {
data_handler().AddDataListener(handle, cb);
}
uint8_t DeviceSampleControl(uint8_t handle, bool enable, CommonCommandCallback cb, void *data) {
uint8_t req = enable;
bool result = command_handler().SendCommand(handle,
kCommandSetGeneral,
kCommandIDGeneralControlSample,
&req,
sizeof(req),
MakeCommandCallback<uint8_t>(cb, data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t LidarStartSampling(uint8_t handle, CommonCommandCallback cb, void *data) {
if (device_manager().device_mode() != kDeviceModeLidar) {
return kStatusNotSupported;
}
return DeviceSampleControl(handle, true, cb, data);
}
uint8_t LidarStopSampling(uint8_t handle, CommonCommandCallback cb, void *data) {
if (device_manager().device_mode() != kDeviceModeLidar) {
return kStatusNotSupported;
}
return DeviceSampleControl(handle, false, cb, data);
}
uint8_t HubStartSampling(CommonCommandCallback cb, void *client_data) {
if (device_manager().device_mode() != kDeviceModeHub) {
return kStatusNotSupported;
}
return DeviceSampleControl(kHubDefaultHandle, true, cb, client_data);
}
uint8_t HubStopSampling(CommonCommandCallback cb, void *client_data) {
if (device_manager().device_mode() != kDeviceModeHub) {
return kStatusNotSupported;
}
return DeviceSampleControl(kHubDefaultHandle, false, cb, client_data);
}
uint8_t HubGetLidarHandle(uint8_t slot, uint8_t id) {
return (slot - 1) * 3 + id - 1;
}
uint8_t QueryDeviceInformation(uint8_t handle, DeviceInformationCallback cb, void *data) {
bool result = command_handler().SendCommand(handle,
kCommandSetGeneral,
kCommandIDGeneralDeviceInfo,
NULL,
0,
MakeCommandCallback<DeviceInformationResponse>(cb, data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t SetCartesianCoordinate(uint8_t handle, CommonCommandCallback cb, void *client_data) {
uint8_t req = 0;
bool result = command_handler().SendCommand(handle,
kCommandSetGeneral,
kCommandIDGeneralCoordinateSystem,
&req,
sizeof(req),
MakeCommandCallback<uint8_t>(cb, client_data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t SetSphericalCoordinate(uint8_t handle, CommonCommandCallback cb, void *client_data) {
uint8_t req = 1;
bool result = command_handler().SendCommand(handle,
kCommandSetGeneral,
kCommandIDGeneralCoordinateSystem,
&req,
sizeof(req),
MakeCommandCallback<uint8_t>(cb, client_data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t SetErrorMessageCallback(uint8_t handle, ErrorMessageCallback cb) {
bool result = command_handler().RegisterPush(
handle, kCommandSetGeneral, kCommandIDGeneralPushAbnormalState, MakeMessageCallback<ErrorMessage>(cb));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t SetStaticDynamicIP(uint8_t handle,
SetDeviceIPModeRequest *req,
CommonCommandCallback cb,
void *client_data) {
bool result = command_handler().SendCommand(handle,
kCommandSetGeneral,
kCommandIDGeneralConfigureStaticDynamicIP,
(uint8_t *)req,
sizeof(*req),
MakeCommandCallback<uint8_t>(cb, client_data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t GetDeviceIPInformation(uint8_t handle, GetDeviceIPInformationCallback cb, void *client_data) {
bool result = command_handler().SendCommand(handle,
kCommandSetGeneral,
kCommandIDGeneralGetDeviceIPInformation,
NULL,
0,
MakeCommandCallback<GetDeviceIPModeResponse>(cb, client_data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t LidarSetMode(uint8_t handle, LidarMode mode, CommonCommandCallback cb, void *client_data) {
if (device_manager().device_mode() != kDeviceModeLidar) {
return kStatusNotSupported;
}
uint8_t req = static_cast<uint8_t>(mode);
bool result = command_handler().SendCommand(handle,
kCommandSetLidar,
kCommandIDLidarSetMode,
&req,
sizeof(req),
MakeCommandCallback<uint8_t>(cb, client_data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t LidarSetExtrinsicParameter(uint8_t handle,
LidarSetExtrinsicParameterRequest *req,
CommonCommandCallback cb,
void *client_data) {
if (device_manager().device_mode() != kDeviceModeLidar) {
return kStatusNotSupported;
}
bool result = command_handler().SendCommand(handle,
kCommandSetLidar,
kCommandIDLidarSetExtrinsicParameter,
(uint8_t *)req,
sizeof(*req),
MakeCommandCallback<uint8_t>(cb, client_data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t LidarGetExtrinsicParameter(uint8_t handle, LidarGetExtrinsicParameterCallback cb, void *client_data) {
if (device_manager().device_mode() != kDeviceModeLidar) {
return kStatusNotSupported;
}
bool result = command_handler().SendCommand(handle,
kCommandSetLidar,
kCommandIDLidarGetExtrinsicParameter,
NULL,
0,
MakeCommandCallback<LidarGetExtrinsicParameterResponse>(cb, client_data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t LidarRainFogSuppress(uint8_t handle, bool enable, CommonCommandCallback cb, void *data) {
uint8_t req = static_cast<uint8_t>(enable);
bool result = command_handler().SendCommand(handle,
kCommandSetLidar,
kCommandIDLidarControlRainFogSuppression,
&req,
sizeof(req),
MakeCommandCallback<uint8_t>(cb, data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t HubQueryLidarInformation(HubQueryLidarInformationCallback cb, void *client_data) {
if (device_manager().device_mode() != kDeviceModeHub) {
return kStatusNotSupported;
}
bool result = command_handler().SendCommand(kHubDefaultHandle,
kCommandSetHub,
kCommandIDHubQueryLidarInformation,
NULL,
0,
MakeCommandCallback<HubQueryLidarInformationResponse>(cb, client_data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t HubSetMode(HubSetModeRequest *req, uint16_t length, HubSetModeCallback cb, void *client_data) {
if (device_manager().device_mode() != kDeviceModeHub) {
return kStatusNotSupported;
}
bool result = command_handler().SendCommand(kHubDefaultHandle,
kCommandSetHub,
kCommandIDHubSetMode,
(uint8_t *)req,
length,
MakeCommandCallback<HubSetModeResponse>(cb, client_data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t HubControlSlotPower(HubControlSlotPowerRequest *req, CommonCommandCallback cb, void *client_data) {
if (device_manager().device_mode() != kDeviceModeHub) {
return kStatusNotSupported;
}
bool result = command_handler().SendCommand(kHubDefaultHandle,
kCommandSetHub,
kCommandIDHubControlSlotPower,
(uint8_t *)req,
sizeof(*req),
MakeCommandCallback<uint8_t>(cb, client_data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t HubSetExtrinsicParameter(HubSetExtrinsicParameterRequest *req,
uint16_t length,
HubSetExtrinsicParameterCallback cb,
void *client_data) {
if (device_manager().device_mode() != kDeviceModeHub) {
return kStatusNotSupported;
}
bool result = command_handler().SendCommand(kHubDefaultHandle,
kCommandSetHub,
kCommandIDHubSetExtrinsicParameter,
(uint8_t *)req,
length,
MakeCommandCallback<HubSetExtrinsicParameterResponse>(cb, client_data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t HubGetExtrinsicParameter(HubGetExtrinsicParameterRequest *req,
uint16_t length,
HubGetExtrinsicParameterCallback cb,
void *client_data) {
if (device_manager().device_mode() != kDeviceModeHub) {
return kStatusNotSupported;
}
bool result = command_handler().SendCommand(kHubDefaultHandle,
kCommandSetHub,
kCommandIDHubGetExtrinsicParameter,
(uint8_t *)req,
length,
MakeCommandCallback<HubGetExtrinsicParameterResponse>(cb, client_data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t HubQueryLidarStatus(HubQueryLidarStatusCallback cb, void *client_data) {
if (device_manager().device_mode() != kDeviceModeHub) {
return kStatusNotSupported;
}
bool result = command_handler().SendCommand(kHubDefaultHandle,
kCommandSetHub,
kCommandIDHubQueryLidarDeviceStatus,
NULL,
0,
MakeCommandCallback<HubQueryLidarStatusResponse>(cb, client_data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t HubExtrinsicParameterCalculation(bool enable, CommonCommandCallback cb, void *client_data) {
if (device_manager().device_mode() != kDeviceModeHub) {
return kStatusNotSupported;
}
uint8_t req = static_cast<uint8_t>(enable);
bool result = command_handler().SendCommand(kHubDefaultHandle,
kCommandSetHub,
kCommandIDHubExtrinsicParameterCalculation,
&req,
sizeof(req),
MakeCommandCallback<uint8_t>(cb, client_data));
return result ? kStatusSuccess : kStatusFailure;
}
uint8_t HubRainFogSuppress(HubRainFogSuppressRequest *req,
uint16_t length,
HubRainFogSuppressCallback cb,
void *client_data) {
if (device_manager().device_mode() != kDeviceModeHub) {
return kStatusNotSupported;
}
bool result = command_handler().SendCommand(kHubDefaultHandle,
kCommandSetHub,
kCommandIDHubRainFogSuppression,
(uint8_t *)req,
length,
MakeCommandCallback<HubRainFogSuppressResponse>(cb, client_data));
return result ? kStatusSuccess : kStatusFailure;
}
+196
View File
@@ -0,0 +1,196 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_SDK_COMMAND_IMPL_H
#define LIVOX_SDK_COMMAND_IMPL_H
namespace livox {
/** The maximum buffer size of command */
static const uint32_t kMaxCommandBufferSize = 1536;
static const uint16_t KDefaultTimeOut = 500;
/** Enum that represents the index of command set. */
typedef enum {
kCommandSetGeneral = 0, /**< general command set. */
kCommandSetLidar, /**< LiDAR command set. */
kCommandSetHub /**< hub command set. */
} CommandSet;
/** Enum that represents the command id. */
typedef enum {
/** General command set, broadcast command. */
kCommandIDGeneralBroadcast = 0,
/**
* General command set, handshake command. When received broadcast from a Livox LiDAR or Hub, a handshake command
* should be sent back to the same port to negotiate connection with the device.
*/
kCommandIDGeneralHandshake = 1,
/**
* General command set, query the information of device.
*/
kCommandIDGeneralDeviceInfo = 2,
/**
* General command set, heartbeat command. after connected, a heartbeat command should be sent at least every second.
*/
kCommandIDGeneralHeartbeat = 3,
/**
* General command set, enable or disable the sampling.
*
*/
kCommandIDGeneralControlSample = 4,
/**
* General command set, change the coordinate of point cloud data.
*/
kCommandIDGeneralCoordinateSystem = 5,
/**
* General command set, disconnect the device.
*/
kCommandIDGeneralDisconnect = 6,
/**
* General command set, a message command from a connected device to notify exceptions, in 10Hz.
*/
kCommandIDGeneralPushAbnormalState = 7,
/**
* General command set, set the IP of the a device.
*/
kCommandIDGeneralConfigureStaticDynamicIP = 8,
/**
* General command set, get the IP of the a device.
*/
kCommandIDGeneralGetDeviceIPInformation = 9,
/**
* ******************************************************
* Don't add command id after kCommandIDGeneralCommandCount.
*/
kCommandIDGeneralCommandCount
} GeneralCommandID;
static const uint16_t GeneralCommandTimeout[kCommandIDGeneralCommandCount] = {KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut};
/** Enum that represents the command id. */
typedef enum {
/**
* Lidar command set, set the working mode and sub working mode of a LiDAR.
*/
kCommandIDLidarSetMode = 0,
/**
* Lidar command set, set the parameters of a LiDAR.
*/
kCommandIDLidarSetExtrinsicParameter = 1,
/**
* Lidar command set, get the parameters of a LiDAR.
*/
kCommandIDLidarGetExtrinsicParameter = 2,
/**
* Lidar command set, enable or disable the rain/fog suppression of a LiDAR.
*/
kCommandIDLidarControlRainFogSuppression = 3,
/**
* ******************************************************
* Don't add command id after kCommandIDLidarCommandCount.
*/
kCommandIDLidarCommandCount
} LidarCommandID;
static const uint16_t LidarCommandTimeout[kCommandIDLidarCommandCount] = {KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut};
/** Enum that represents the command id. */
typedef enum {
/**
* Hub command set, get the information of connected Livox LiDAR.
*/
kCommandIDHubQueryLidarInformation = 0,
/**
* Hub command set, set the working mode of connected Livox LiDAR.
*/
kCommandIDHubSetMode = 1,
/**
* Hub command set, enable or disable the power supply of the hub slot.
*/
kCommandIDHubControlSlotPower = 2,
/**
* Hub command set, set the parameters of connected Livox LiDAR.
*/
kCommandIDHubSetExtrinsicParameter = 3,
/**
* Hub command set, get the parameters of connected Livox LiDAR.
*/
kCommandIDHubGetExtrinsicParameter = 4,
/**
* Hub command set, get the working state of the connected Livox LiDAR.
*/
kCommandIDHubQueryLidarDeviceStatus = 5,
/**
* Hub command set, enable or disable calculating the parameters.
*/
kCommandIDHubExtrinsicParameterCalculation = 6,
/**
* Hub command set, open or close the rain and fog mode of the connected Livox LiDAR.
*/
kCommandIDHubRainFogSuppression = 7,
/**
* ******************************************************
* Don't add command id after kCommandIDHubCommandCount.
*/
kCommandIDHubCommandCount
} HubCommandID;
static const uint16_t HubCommandTimeout[kCommandIDHubCommandCount] = {KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut,
KDefaultTimeOut};
/**
* Enum that represents the command type.
*/
typedef enum {
/** command type, which requires response from the receiver. */
kCommandTypeCmd = 0,
/** acknowledge type, which is the response of command type. */
kCommandTypeAck = 1,
/** message type, which is sent at a specified frequency. */
kCommandTypeMsg = 2
} CommandType;
} // namespace livox
#endif // LIVOX_SDK_COMMAND_IMPL_H
@@ -0,0 +1,65 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "hub_command_handler.h"
#include "base/network_util.h"
namespace livox {
void HubCommandHandlerImpl::Uninit() {
if (channel_) {
channel_.reset(NULL);
}
is_valid_ = false;
}
bool HubCommandHandlerImpl::AddDevice(const DeviceInfo &info) {
if (is_valid_) {
return false;
}
is_valid_ = true;
hub_info_ = info;
channel_.reset(new CommandChannel(info.cmd_port, info.handle, info.ip, this, mem_pool_));
channel_->Bind(loop_);
return true;
}
bool HubCommandHandlerImpl::SendCommand(uint8_t, const Command &command) {
if (channel_ == NULL) {
return false;
}
channel_->SendAsync(command);
return true;
}
bool HubCommandHandlerImpl::RemoveDevice(uint8_t) {
is_valid_ = false;
if (channel_) {
channel_.reset(NULL);
}
return false;
}
} // namespace livox
@@ -0,0 +1,49 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_HUB_COMMAND_HANDLER_H_
#define LIVOX_HUB_COMMAND_HANDLER_H_
#include <boost/scoped_ptr.hpp>
#include "command_handler.h"
namespace livox {
class HubCommandHandlerImpl : public CommandHandlerImpl {
public:
HubCommandHandlerImpl(CommandHandler *handler, apr_pool_t *pool, IOLoop *loop)
: CommandHandlerImpl(handler), mem_pool_(pool), loop_(loop), is_valid_(false) {}
void Uninit();
bool AddDevice(const DeviceInfo &info);
bool RemoveDevice(uint8_t handle);
bool SendCommand(uint8_t handle, const Command &command);
private:
apr_pool_t *mem_pool_;
IOLoop *loop_;
bool is_valid_;
DeviceInfo hub_info_;
boost::scoped_ptr<CommandChannel> channel_;
};
} // namespace livox
#endif // LIVOX_HUB_COMMAND_HANDLER_H_
@@ -0,0 +1,74 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "lidar_command_handler.h"
using std::list;
namespace livox {
void LidarCommandHandlerImpl::Uninit() {
devices_.clear();
}
bool LidarCommandHandlerImpl::AddDevice(const DeviceInfo &info) {
boost::shared_ptr<CommandChannel> channel =
boost::make_shared<CommandChannel>(info.cmd_port, info.handle, info.ip, this, mem_pool_);
channel->Bind(loop_);
DeviceItem item = {channel, info};
devices_.push_back(item);
return true;
}
bool LidarCommandHandlerImpl::SendCommand(uint8_t handle, const Command &command) {
CommandChannel *channel = NULL;
for (list<DeviceItem>::iterator ite = devices_.begin(); ite != devices_.end(); ++ite) {
if (ite->info.handle == handle) {
channel = ite->channel.get();
break;
}
}
if (channel) {
channel->SendAsync(command);
return true;
}
return false;
}
bool LidarCommandHandlerImpl::RemoveDevice(uint8_t handle) {
bool found = false;
for (list<DeviceItem>::iterator ite = devices_.begin(); ite != devices_.end(); ++ite) {
if (ite->info.handle == handle) {
found = true;
devices_.erase(ite);
break;
}
}
return found;
}
} // namespace livox
@@ -0,0 +1,55 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_LIDAR_COMMAND_HANDLER_H_
#define LIVOX_LIDAR_COMMAND_HANDLER_H_
#include <boost/smart_ptr.hpp>
#include "command_handler.h"
namespace livox {
class LidarCommandHandlerImpl : public CommandHandlerImpl {
public:
LidarCommandHandlerImpl(CommandHandler *handler, apr_pool_t *pool, IOLoop *loop)
: CommandHandlerImpl(handler), mem_pool_(pool), loop_(loop) {}
void Uninit();
bool AddDevice(const DeviceInfo &info);
bool RemoveDevice(uint8_t handle);
bool SendCommand(uint8_t handle, const Command &command);
private:
typedef struct {
boost::shared_ptr<CommandChannel> channel;
DeviceInfo info;
} DeviceItem;
apr_pool_t *mem_pool_;
std::list<DeviceItem> devices_;
IOLoop *loop_;
};
} // namespace livox
#endif // LIVOX_LIDAR_COMMAND_HANDLER_H_
+124
View File
@@ -0,0 +1,124 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "data_handler.h"
#include <base/logging.h>
#include "hub_data_handler.h"
#include "lidar_data_handler.h"
namespace livox {
static const size_t kSphericalCoordinatePointSize = 9;
static const size_t kCartesianCoordinatePointSize = 13;
static const size_t kPrefixDataSize = 18;
DataHandler &data_handler() {
static DataHandler handler;
return handler;
}
#pragma pack(1)
#pragma pack()
bool DataHandler::AddDataListener(uint8_t handle, const DataCallback &cb) {
if (handle >= callbacks_.size()) {
return false;
}
callbacks_[handle] = cb;
return true;
}
bool DataHandler::AddDevice(const DeviceInfo &info) {
if (impl_ == NULL) {
DeviceMode mode = static_cast<DeviceMode>(device_manager().device_mode());
if (mode == kDeviceModeHub) {
impl_.reset(new HubDataHandlerImpl(this, mem_pool_));
} else if (mode == kDeviceModeLidar) {
impl_.reset(new LidarDataHandlerImpl(this, mem_pool_));
}
if (impl_ == NULL || !impl_->Init()) {
impl_.reset(NULL);
return false;
}
}
return impl_->AddDevice(info);
}
bool DataHandler::Init() {
apr_status_t rv = apr_pool_create(&mem_pool_, NULL);
if (rv != APR_SUCCESS) {
return false;
}
return true;
}
void DataHandler::Uninit() {
if (impl_) {
impl_.reset(NULL);
}
if (mem_pool_) {
apr_pool_destroy(mem_pool_);
mem_pool_ = NULL;
}
}
void DataHandler::OnDataCallback(uint8_t handle, void *data, uint16_t size) {
LivoxEthPacket *lidar_data = (LivoxEthPacket *)data;
if (lidar_data == NULL) {
return;
}
if (handle >= callbacks_.size()) {
return;
}
DataCallback cb = callbacks_[handle];
if (lidar_data->data_type == 0) {
size = (size - kPrefixDataSize) / kCartesianCoordinatePointSize;
} else if (lidar_data->data_type == 1) {
size = (size - kPrefixDataSize) / kSphericalCoordinatePointSize;
} else {
return;
}
if (cb) {
// LOG_INFO << " device_sn: " << device_sn << std::endl;
// LOG_INFO << " version: " << (uint32_t) lidar_data_cb->version << std::endl;
// LOG_INFO << " slot: " << (uint32_t) lidar_data_cb->slot << std::endl;
// LOG_INFO << " resverd : " << (uint32_t) lidar_data_cb->reserved << std::endl;
// LOG_INFO << " errorCode: " << (uint32_t) lidar_data_cb->err_code << std::endl;
// LOG_INFO << " lidarID: " << (uint16_t) lidar_data_cb->id << std::endl;
// LOG_INFO << " timeStampType: " << (uint32_t) (lidar_data_cb->timestamp_type) << std::endl;
// LOG_INFO << " timeStamp: " << (uint32_t) *(lidar_data_cb->time_stamp) << std::endl;
// LOG_INFO << " dataType: " << (uint16_t) lidar_data->data_type << std::endl << std::endl;
cb(handle, lidar_data, size);
}
}
void DataHandler::RemoveDevice(uint8_t handle) {
if (impl_) {
impl_->RemoveDevice(handle);
}
}
} // namespace livox
+87
View File
@@ -0,0 +1,87 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_DATA_HANDLER_H_
#define LIVOX_DATA_HANDLER_H_
#include <boost/array.hpp>
#include <boost/function.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/thread/mutex.hpp>
#include "apr_pools.h"
#include "base/io_thread.h"
#include "device_manager.h"
namespace livox {
class DataHandlerImpl;
class DataHandler : public noncopyable {
public:
typedef boost::function<void(uint8_t handle, LivoxEthPacket *data, uint32_t data_num)> DataCallback;
public:
DataHandler() : mem_pool_(NULL) {}
bool Init();
void Uninit();
bool AddDevice(const DeviceInfo &info);
void RemoveDevice(uint8_t handle);
bool AddDataListener(uint8_t handle, const DataCallback &cb);
// bool RemoveDataListener(uint8_t handle);
void OnDataCallback(uint8_t handle, void *data, uint16_t size);
private:
apr_pool_t *mem_pool_;
boost::array<DataCallback, kMaxConnectedDeviceNum> callbacks_;
boost::scoped_ptr<DataHandlerImpl> impl_;
};
class DataHandlerImpl : public IOLoop::IOLoopDelegate {
public:
DataHandlerImpl(DataHandler *handler) : handler_(handler) {}
virtual ~DataHandlerImpl() {}
virtual bool Init() = 0;
virtual void Uninit(){};
virtual bool AddDevice(const DeviceInfo &info) = 0;
virtual void RemoveDevice(uint8_t handle) = 0;
void OnDataCallback(uint8_t handle, void *data, uint16_t size) {
if (handler_) {
handler_->OnDataCallback(handle, data, size);
}
}
protected:
static const size_t kMaxBufferSize = 8192;
DataHandler *handler_;
};
DataHandler &data_handler();
} // namespace livox
#endif // LIVOX_DATA_HANDLER_H_
@@ -0,0 +1,93 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "hub_data_handler.h"
#include <base/logging.h>
#include "base/network_util.h"
namespace livox {
bool HubDataHandlerImpl::Init() {
if (thread_->Init(false, false)) {
return thread_->Start();
}
return false;
}
void HubDataHandlerImpl::Uninit() {
if (thread_) {
thread_->Quit();
thread_->Join();
thread_->Uninit();
thread_.reset(NULL);
}
if (sock_) {
apr_socket_close(sock_);
sock_ = NULL;
}
is_valid_ = false;
mem_pool_ = NULL;
}
bool HubDataHandlerImpl::AddDevice(const DeviceInfo &info) {
if (is_valid_) {
return false;
}
is_valid_ = true;
hub_info_ = info;
sock_ = util::CreateBindSocket(info.data_port, mem_pool_);
if (sock_ == NULL) {
is_valid_ = false;
return false;
}
thread_->loop()->AddDelegate(sock_, this);
return true;
}
void HubDataHandlerImpl::OnData(apr_socket_t *, void *) {
apr_sockaddr_t addr;
if (buf_.size() < kMaxBufferSize) {
buf_.resize(kMaxBufferSize);
}
apr_size_t size = kMaxBufferSize;
apr_socket_recvfrom(&addr, sock_, 0, &buf_[0], &size);
if (handler_) {
handler_->OnDataCallback(hub_info_.handle, &buf_[0], size);
}
}
void HubDataHandlerImpl::RemoveDevice(uint8_t handle) {
if (handle == hub_info_.handle) {
thread_->loop()->RemoveDelegate(sock_, this);
apr_socket_close(sock_);
sock_ = NULL;
is_valid_ = false;
}
}
} // namespace livox
@@ -0,0 +1,57 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_HUB_DATA_HANDLER_H_
#define LIVOX_HUB_DATA_HANDLER_H_
#include <boost/smart_ptr.hpp>
#include "base/io_thread.h"
#include "data_handler.h"
namespace livox {
class HubDataHandlerImpl : public DataHandlerImpl {
public:
HubDataHandlerImpl(DataHandler *handler, apr_pool_t *mem_pool)
: DataHandlerImpl(handler), mem_pool_(mem_pool), thread_(new IOThread()), sock_(NULL), is_valid_(false) {}
~HubDataHandlerImpl() { Uninit(); }
bool Init();
void Uninit();
bool AddDevice(const DeviceInfo &info);
void RemoveDevice(uint8_t t);
void OnData(apr_socket_t *sock, void *client_data);
private:
apr_pool_t *mem_pool_;
boost::scoped_ptr<IOThread> thread_;
apr_socket_t *sock_;
DeviceInfo hub_info_;
bool is_valid_;
std::vector<char> buf_;
};
} // namespace livox
#endif // LIVOX_HUB_DATA_HANDLER_H_
@@ -0,0 +1,123 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "lidar_data_handler.h"
#include <boost/thread/lock_guard.hpp>
#include <boost/thread/locks.hpp>
#include "base/network_util.h"
using boost::lock_guard;
using boost::mutex;
using boost::shared_ptr;
using std::list;
namespace livox {
bool LidarDataHandlerImpl::Init() {
return true;
}
void LidarDataHandlerImpl::Uninit() {
for (list<DeviceItem>::iterator ite = devices_.begin(); ite != devices_.end(); ++ite) {
DeviceItem &item = *ite;
if (item.thread) {
if (item.thread->loop()) {
item.thread->loop()->RemoveDelegate(item.sock, this);
}
item.thread->Quit();
item.thread->Join();
item.thread->Uninit();
}
if (item.sock) {
apr_socket_close(item.sock);
}
}
devices_.clear();
}
bool LidarDataHandlerImpl::AddDevice(const DeviceInfo &info) {
apr_socket_t *sock = util::CreateBindSocket(info.data_port, mem_pool_);
if (sock == NULL) {
return false;
}
shared_ptr<IOThread> thread = boost::make_shared<IOThread>();
thread->Init(false, false);
thread->loop()->AddDelegate(sock, this, reinterpret_cast<void *>(info.handle));
{
lock_guard<mutex> lock(mutex_);
DeviceItem item = {sock, thread, info.handle};
devices_.push_back(item);
}
return thread->Start();
}
void LidarDataHandlerImpl::RemoveDevice(uint8_t handle) {
DeviceItem item;
bool found = false;
{
lock_guard<mutex> lock(mutex_);
for (list<DeviceItem>::iterator ite = devices_.begin(); ite != devices_.end(); ++ite) {
if (ite->handle == handle) {
item = *ite;
found = true;
devices_.erase(ite);
break;
}
}
}
if (found) {
item.thread->loop()->RemoveDelegate(item.sock, this);
item.thread->Quit();
item.thread->Join();
item.thread->Uninit();
if (item.sock) {
apr_socket_close(item.sock);
}
}
}
void LidarDataHandlerImpl::OnData(apr_socket_t *sock, void *client_data) {
uint8_t handle = static_cast<uint8_t>(reinterpret_cast<uintptr_t>(client_data));
if (handle > data_buffers_.size()) {
return;
}
boost::scoped_array<char> &buf = data_buffers_[handle];
if (buf.get() == NULL) {
buf.reset(new char[kMaxBufferSize]);
}
apr_sockaddr_t addr;
apr_size_t size = kMaxBufferSize;
if (APR_SUCCESS == apr_socket_recvfrom(&addr, sock, 0, buf.get(), &size)) {
if (handler_) {
handler_->OnDataCallback(handle, buf.get(), size);
}
}
}
} // namespace livox
@@ -0,0 +1,61 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_LIDAR_DATA_HANDLER_H_
#define LIVOX_LIDAR_DATA_HANDLER_H_
#include <boost/shared_ptr.hpp>
#include <boost/smart_ptr/scoped_array.hpp>
#include <boost/thread/mutex.hpp>
#include "data_handler.h"
#include "device_manager.h"
namespace livox {
class LidarDataHandlerImpl : public DataHandlerImpl {
public:
LidarDataHandlerImpl(DataHandler *handler, apr_pool_t *mem_pool) : DataHandlerImpl(handler), mem_pool_(mem_pool) {}
~LidarDataHandlerImpl() { Uninit(); }
bool Init();
void Uninit();
bool AddDevice(const DeviceInfo &info);
void RemoveDevice(uint8_t handle);
void OnData(apr_socket_t *sock, void *client_data);
private:
typedef struct {
apr_socket_t *sock;
boost::shared_ptr<IOThread> thread;
uint16_t handle;
} DeviceItem;
std::list<DeviceItem> devices_;
boost::array<boost::scoped_array<char>, kMaxConnectedDeviceNum> data_buffers_;
apr_pool_t *mem_pool_;
boost::mutex mutex_;
};
} // namespace livox
#endif // LIVOX_LIDAR_DATA_HANDLER_H_
+247
View File
@@ -0,0 +1,247 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "device_discovery.h"
#include <algorithm>
#include <boost/thread/lock_guard.hpp>
#include <boost/thread/locks.hpp>
#include <iostream>
#include <vector>
#include "apr_network_io.h"
#include "apr_pools.h"
#include "arpa/inet.h"
#include "base/logging.h"
#include "base/network_util.h"
#include "command_handler/command_impl.h"
#include "device_manager.h"
#include "livox_def.h"
using boost::tuple;
using std::string;
using std::vector;
namespace livox {
uint16_t DeviceDiscovery::port_count = 0;
bool DeviceDiscovery::Init() {
apr_status_t rv = apr_pool_create(&mem_pool_, NULL);
if (rv != APR_SUCCESS) {
LOG_ERROR << PrintAPRStatus(rv) << std::endl;
return false;
}
if (comm_port_ == NULL) {
comm_port_.reset(new CommPort());
}
return true;
}
bool DeviceDiscovery::Start(IOLoop *loop) {
if (loop == NULL) {
return false;
}
loop_ = loop;
sock_ = util::CreateBindSocket(kListenPort, mem_pool_);
if (sock_ == NULL) {
LOG_ERROR << "DeviceDiscovery Create Socket Failed" << std::endl;
return false;
}
loop_->AddDelegate(sock_, this);
return true;
}
void DeviceDiscovery::OnData(apr_socket_t *sock, void *) {
apr_sockaddr_t addr;
uint32_t buf_size = 0;
uint8_t *cache_buf = comm_port_->FetchCacheFreeSpace(&buf_size);
apr_size_t size = buf_size;
apr_status_t rv = apr_socket_recvfrom(&addr, sock, 0, reinterpret_cast<char *>(cache_buf), &size);
comm_port_->UpdateCacheWrIdx(size);
if (rv != APR_SUCCESS) {
LOG_ERROR << " Receive Failed " << PrintAPRStatus(rv) << std::endl;
return;
}
CommPacket packet;
memset(&packet, 0, sizeof(packet));
while ((kParseSuccess == comm_port_->ParseCommStream(&packet))) {
if (packet.cmd_set == kCommandSetGeneral && packet.cmd_code == kCommandIDGeneralBroadcast) {
OnBroadcast(packet, &addr);
} else if (packet.cmd_set == kCommandSetGeneral && packet.cmd_code == kCommandIDGeneralHandshake) {
if (connecting_devices_.find(sock) == connecting_devices_.end()) {
continue;
}
DeviceInfo info = boost::get<2>(connecting_devices_[sock]);
loop_->RemoveDelegate(sock, this);
apr_socket_close(sock);
apr_pool_destroy(boost::get<0>(connecting_devices_[sock]));
connecting_devices_.erase(sock);
if (packet.data == NULL) {
continue;
}
if (*(uint8_t *)packet.data == 0) {
LOG_INFO << "New Device " << std::endl;
LOG_INFO << "Handle: " << static_cast<uint16_t>(info.handle) << std::endl;
LOG_INFO << "Broadcast Code: " << info.broadcast_code << std::endl;
LOG_INFO << "Type: " << info.type << std::endl;
LOG_INFO << "IP: " << info.ip << std::endl;
LOG_INFO << "Command Port: " << info.cmd_port << std::endl;
LOG_INFO << "Data Port: " << info.data_port << std::endl;
LOG_INFO << std::endl;
DeviceFound(info);
}
}
}
}
void DeviceDiscovery::OnTimer(apr_time_t now) {
ConnectingDeviceMap::iterator ite = connecting_devices_.begin();
while (ite != connecting_devices_.end()) {
tuple<apr_pool_t *, apr_time_t, DeviceInfo> &device_tuple = ite->second;
if (now - boost::get<1>(device_tuple) > apr_time_from_msec(500)) {
loop_->RemoveDelegate(ite->first, this);
apr_socket_close(ite->first);
apr_pool_destroy(boost::get<0>(device_tuple));
connecting_devices_.erase(ite++);
} else {
++ite;
}
}
}
void DeviceDiscovery::Uninit() {
if (sock_) {
apr_socket_close(sock_);
sock_ = NULL;
}
if (comm_port_) {
comm_port_.reset(NULL);
}
if (mem_pool_) {
apr_pool_destroy(mem_pool_);
mem_pool_ = NULL;
}
}
void DeviceDiscovery::OnBroadcast(const CommPacket &packet, apr_sockaddr_t *addr) {
if (packet.data == NULL) {
return;
}
BroadcastDeviceInfo *device_info = (BroadcastDeviceInfo *)packet.data;
string broadcast_code = device_info->broadcast_code;
//LOG_INFO << " Boradcast broadcast code: " << broadcast_code << std::endl;
device_manager().BroadcastDevices(device_info);
DeviceInfo lidar_info;
bool found = device_manager().FindDevice(broadcast_code, lidar_info);
if (!found || device_manager().IsDeviceConnected(lidar_info.handle)) {
return;
}
++port_count;
strncpy(lidar_info.broadcast_code, broadcast_code.c_str(), sizeof(lidar_info.broadcast_code));
lidar_info.cmd_port = kListenPort + kCmdPortOffset + port_count;
lidar_info.data_port = kListenPort + kDataPortOffset + port_count;
lidar_info.type = device_info->dev_type;
lidar_info.state = kLidarStateUnknown;
lidar_info.feature = kLidarFeatureNone;
lidar_info.status.status_code = 0;
char ip[16];
memset(&ip, 0, sizeof(ip));
apr_status_t rv = apr_sockaddr_ip_getbuf(ip, sizeof(ip), addr);
if (rv != APR_SUCCESS) {
LOG_ERROR << PrintAPRStatus(rv) << std::endl;
return;
}
strncpy(lidar_info.ip, ip, sizeof(lidar_info.ip));
apr_pool_t *pool = NULL;
rv = apr_pool_create(&pool, mem_pool_);
if (rv != APR_SUCCESS) {
LOG_ERROR << PrintAPRStatus(rv) << std::endl;
return;
}
apr_socket_t *cmd_sock = util::CreateBindSocket(lidar_info.cmd_port, pool);
if (cmd_sock == NULL) {
apr_pool_destroy(pool);
pool = NULL;
return;
}
loop_->AddDelegate(cmd_sock, this);
OnTimer(apr_time_now());
boost::get<0>(connecting_devices_[cmd_sock]) = pool;
boost::get<2>(connecting_devices_[cmd_sock]) = lidar_info;
bool result = false;
do {
HandshakeRequest handshake_req;
uint32_t local_ip = 0;
if (util::FindLocalIP(addr->sa.sin, local_ip) == false) {
result = false;
break;
}
CommPacket packet;
memset(&packet, 0, sizeof(packet));
handshake_req.ip_addr = local_ip;
handshake_req.cmd_port = lidar_info.cmd_port;
handshake_req.data_port = lidar_info.data_port;
packet.packet_type = kCommandTypeAck;
packet.seq_num = CommandChannel::GenerateSeq();
packet.cmd_set = kCommandSetGeneral;
packet.cmd_code = kCommandIDGeneralHandshake;
packet.data_len = sizeof(handshake_req);
packet.data = (uint8_t *)&handshake_req;
vector<uint8_t> buf(kMaxCommandBufferSize + 1);
apr_size_t o_len = kMaxCommandBufferSize;
comm_port_->Pack(buf.data(), kMaxCommandBufferSize, (uint32_t *)&o_len, packet);
rv = apr_socket_sendto(cmd_sock, addr, 0, reinterpret_cast<const char *>(buf.data()), &o_len);
if (rv != APR_SUCCESS) {
result = false;
break;
}
boost::get<1>(connecting_devices_[cmd_sock]) = apr_time_now();
result = true;
} while (0);
if (result == false) {
loop_->RemoveDelegate(cmd_sock, this);
apr_socket_close(cmd_sock);
apr_pool_destroy(pool);
connecting_devices_.erase(cmd_sock);
}
}
DeviceDiscovery &device_discovery() {
static DeviceDiscovery discovery;
return discovery;
}
} // namespace livox
+89
View File
@@ -0,0 +1,89 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_DEVICE_DISCOVERY_
#define LIVOX_DEVICE_DISCOVERY_
#include <boost/thread/mutex.hpp>
#include <string>
#include "apr_general.h"
#include "apr_network_io.h"
#include "apr_pools.h"
#include "base/io_thread.h"
#include "base/noncopyable.h"
#include "comm/comm_port.h"
#include "command_handler/command_channel.h"
namespace livox {
/**
* DeviceDiscovery listens broadcast message from devices, and proceed handshake
* if device is in the listening list.
*/
class DeviceDiscovery : public noncopyable, IOLoop::IOLoopDelegate {
public:
DeviceDiscovery() : sock_(NULL), mem_pool_(NULL), loop_(NULL), comm_port_(NULL) {}
bool Init();
void Uninit();
/**
* start the listening of broadcast UDP message.
* @param loop IOLoop on where DeviceDiscovery runs.
* @return true if successfully.
*/
bool Start(IOLoop *loop);
/**
* IOLoop callback delegate.
* @param client_data client data passed in IOLoop::AddDelegate
*/
void OnData(apr_socket_t *, void *client_data);
void OnTimer(apr_time_t now);
private:
void OnBroadcast(const CommPacket &packet, apr_sockaddr_t *addr);
private:
/** broadcast listening port number. */
static const apr_port_t kListenPort = 55000;
/** command port number start offset. */
static const apr_port_t kCmdPortOffset = 500;
/** data port number start offset. */
static const apr_port_t kDataPortOffset = 1000;
static uint16_t port_count;
apr_socket_t *sock_;
apr_pool_t *mem_pool_;
IOLoop *loop_;
boost::scoped_ptr<CommPort> comm_port_;
boost::mutex mutex_;
typedef std::map<apr_socket_t *, boost::tuple<apr_pool_t *, apr_time_t, DeviceInfo> > ConnectingDeviceMap;
ConnectingDeviceMap connecting_devices_;
};
DeviceDiscovery &device_discovery();
} // namespace livox
#endif // LIVOX_DEVICE_DISCOVERY_
+260
View File
@@ -0,0 +1,260 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "device_manager.h"
#include <boost/atomic.hpp>
#include <boost/thread/lock_guard.hpp>
#include <boost/thread/locks.hpp>
#include <vector>
#include "base/logging.h"
#include "command_handler/command_handler.h"
#include "command_handler/command_impl.h"
#include "data_handler/data_handler.h"
using boost::lock_guard;
using boost::mutex;
using std::string;
using std::vector;
namespace livox {
inline bool IsHub(uint8_t mode) {
return mode == kDeviceTypeHub;
}
inline bool IsLidar(uint8_t mode) {
return mode == kDeviceTypeLidarTele || mode == kDeviceTypeLidarMid40 || mode == kDeviceTypeLidarHorizon;
}
bool DeviceManager::Init() {
apr_status_t rv = apr_pool_create(&mem_pool_, NULL);
if (rv != APR_SUCCESS) {
return false;
}
return true;
}
void DeviceManager::Uninit() {
broadcast_cb_ = NULL;
connected_cb_ = NULL;
device_mode_ = kDeviceModeNone;
for (DeviceContainer::iterator ite = devices_.begin(); ite != devices_.end(); ++ite) {
ite->clear();
}
if (mem_pool_) {
apr_pool_destroy(mem_pool_);
mem_pool_ = NULL;
}
}
bool DeviceManager::AddDevice(const DeviceInfo &device) {
if (device_mode_ == kDeviceModeNone) {
if (IsHub(device.type)) {
device_mode_ = kDeviceModeHub;
} else if (IsLidar(device.type)) {
device_mode_ = kDeviceModeLidar;
}
}
{
lock_guard<mutex> lock(mutex_);
if (device.handle < devices_.size()) {
DetailDeviceInfo &info = devices_[device.handle];
info.connected = true;
info.info = device;
}
}
return true;
}
void DeviceManager::RemoveDevice(uint8_t handle) {
lock_guard<mutex> lock(mutex_);
if (handle < devices_.size()) {
devices_[handle].connected = false;
}
}
void DeviceManager::BroadcastDevices(const BroadcastDeviceInfo *info) {
if (broadcast_cb_) {
broadcast_cb_(info);
}
}
void DeviceManager::UpdateDevices(const DeviceInfo &device, DeviceEvent type) {
if (device_mode_ == kDeviceModeLidar && connected_cb_) {
connected_cb_(&device, type);
}
if ((device_mode_ == kDeviceModeHub) && (type == kEventConnect)) {
LOG_DEBUG << "Send Query lidars command" << std::endl;
command_handler().SendCommand(kHubDefaultHandle,
kCommandSetHub,
kCommandIDHubQueryLidarInformation,
NULL,
0,
MakeCommandCallback<DeviceManager, HubQueryLidarInformationResponse>(
this, &DeviceManager::HubLidarInfomationCallback));
}
}
void DeviceManager::HubLidarInfomationCallback(uint8_t status, uint8_t, HubQueryLidarInformationResponse *response) {
if (status == kStatusSuccess) {
{
lock_guard<mutex> lock(mutex_);
for (int i = 0; i < response->count; i++) {
std::size_t index = (response->device_info_list[i].slot - 1) * 3 + response->device_info_list[i].id - 1;
if (index < devices_.size()) {
DetailDeviceInfo &info = devices_[index];
info.connected = true;
strncpy(
info.info.broadcast_code, response->device_info_list[i].broadcast_code, sizeof(info.info.broadcast_code));
info.info.handle = index;
}
}
}
if (connected_cb_) {
connected_cb_(&(devices_[kHubDefaultHandle].info), kEventConnect);
}
} else {
LOG_ERROR << "Failed to query lidars information connected to hub." << std::endl;
}
}
void DeviceManager::GetConnectedDevices(vector<DeviceInfo> &devices) {
lock_guard<mutex> lock(mutex_);
for (DeviceContainer::iterator ite = devices_.begin(); ite != devices_.end(); ++ite) {
if (ite->connected == true) {
devices.push_back(ite->info);
}
}
}
bool DeviceManager::AddListeningDevice(const string &broadcast_code, DeviceMode mode, uint8_t &handle) {
lock_guard<mutex> lock(mutex_);
if (mode == kDeviceModeHub) {
handle = kHubDefaultHandle;
devices_[kHubDefaultHandle].connected = false;
strncpy(devices_[kHubDefaultHandle].info.broadcast_code,
broadcast_code.c_str(),
sizeof(devices_[kHubDefaultHandle].info.broadcast_code));
devices_[kHubDefaultHandle].info.handle = kHubDefaultHandle;
return true;
}
for (DeviceContainer::iterator ite = devices_.begin(); ite != devices_.end(); ++ite) {
if (strlen(ite->info.broadcast_code) == 0) {
handle = ite - devices_.begin();
ite->connected = false;
strncpy(ite->info.broadcast_code, broadcast_code.c_str(), sizeof(ite->info.broadcast_code));
ite->info.handle = handle;
return true;
}
}
return false;
}
bool DeviceManager::FindDevice(uint8_t handle, DeviceInfo &info) {
lock_guard<mutex> lock(mutex_);
if (handle >= devices_.size()) {
return false;
}
info = devices_[handle].info;
return true;
}
bool DeviceManager::FindDevice(const string &broadcast_code, DeviceInfo &info) {
lock_guard<mutex> lock(mutex_);
for (DeviceContainer::iterator ite = devices_.begin(); ite != devices_.end(); ++ite) {
if (ite->info.broadcast_code == broadcast_code) {
info = ite->info;
return true;
}
}
return false;
}
bool DeviceManager::IsDeviceConnected(uint8_t handle) {
lock_guard<mutex> lock(mutex_);
if (handle >= devices_.size()) {
return false;
}
return devices_[handle].connected;
}
void DeviceManager::UpdateDeviceState(uint8_t handle, const HeartbeatResponse &response) {
if (handle >= devices_.size()) {
return;
}
// LOG_INFO << " Update State " << (uint16_t) response.state << " connect " << devices_[handle].connected <<
// std::endl;
bool update = false;
DeviceInfo &info = devices_[handle].info;
if (info.state != response.state) {
info.state = static_cast<LidarState>(response.state);
update = true;
}
if (info.feature != response.feature) {
info.feature = static_cast<LidarFeature>(response.feature);
update = true;
}
if (info.status.progress != response.error_union.progress) {
info.status.progress = response.error_union.progress;
update = true;
}
if (devices_[handle].connected && update == true) {
if (connected_cb_) {
connected_cb_(&info, kEventStateChange);
}
}
}
DeviceManager &device_manager() {
static DeviceManager lidar_manager;
return lidar_manager;
}
void DeviceFound(const DeviceInfo &lidar_data) {
device_manager().AddDevice(lidar_data);
command_handler().AddDevice(lidar_data);
data_handler().AddDevice(lidar_data);
device_manager().UpdateDevices(lidar_data, kEventConnect);
}
void DeviceRemove(uint8_t handle) {
DeviceInfo info;
bool found = device_manager().FindDevice(handle, info);
device_manager().RemoveDevice(handle);
command_handler().RemoveDevice(handle);
data_handler().RemoveDevice(handle);
if (found) {
device_manager().UpdateDevices(info, kEventDisconnect);
}
}
} // namespace livox
+156
View File
@@ -0,0 +1,156 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#ifndef LIVOX_DEVICE_MANAGER_H_
#define LIVOX_DEVICE_MANAGER_H_
#include <boost/array.hpp>
#include <boost/function.hpp>
#include <boost/thread/mutex.hpp>
#include <string>
#include "device_discovery.h"
#include "livox_sdk.h"
namespace livox {
/** Maximum number of connected devices supported. */
static const uint8_t kMaxConnectedDeviceNum = 32;
/** Default handle value of hub. */
static const uint8_t kHubDefaultHandle = kMaxConnectedDeviceNum - 1;
/**
* Device connected mode.
*/
typedef enum {
kDeviceModeNone = 0, /**< no devices connected. */
kDeviceModeHub = 1, /**< connected with hub. */
kDeviceModeLidar = 2 /**< connected with lidar. */
} DeviceMode;
/**
* DeviceManager manage all the devices connected, including hub and lidars.
*/
class DeviceManager : public noncopyable {
public:
DeviceManager() : mem_pool_(NULL), device_mode_(kDeviceModeNone), connected_cb_(NULL), broadcast_cb_(NULL) {}
bool Init();
void Uninit();
/**
* When a new device is successfully connected, AddDevice is called to add new device to DeviceManager.
* @param device connected device information.
* @return true if successfully added.
*/
bool AddDevice(const DeviceInfo &device);
/**
* When device is disconnected (not response to the heartbeat command), RemoveDevice is called.
* @param handle connected device handle.
*/
void RemoveDevice(uint8_t handle);
/**
* Find device via handle.
*/
bool FindDevice(uint8_t handle, DeviceInfo &info);
/**
* Find device via broadcast code.
*/
bool FindDevice(const std::string &broadcast_code, DeviceInfo &info);
/**
* Check whether a device is connected.
* @param handle device handle.
* @return true if device is connected.
*/
bool IsDeviceConnected(uint8_t handle);
void SetDeviceConnectedCallback(const boost::function<void(const DeviceInfo *, DeviceEvent)> &cb) {
connected_cb_ = cb;
}
void SetDeviceBroadcastCallback(const boost::function<void(const BroadcastDeviceInfo *info)> &cb) {
broadcast_cb_ = cb;
}
void HubLidarInfomationCallback(uint8_t status, uint8_t handle, HubQueryLidarInformationResponse *response);
DeviceMode device_mode() { return device_mode_; }
void BroadcastDevices(const BroadcastDeviceInfo *info);
void UpdateDevices(const DeviceInfo &device, DeviceEvent type);
void UpdateDeviceState(uint8_t handle, const HeartbeatResponse &response);
void GetConnectedDevices(std::vector<DeviceInfo> &devices);
bool AddListeningDevice(const std::string &broadcast_code, DeviceMode mode, uint8_t &handle);
private:
typedef struct _DetailDeviceInfo {
bool connected;
DeviceInfo info;
_DetailDeviceInfo() { connected = false; }
_DetailDeviceInfo(bool _connected,
const char *broadcast_code,
uint8_t handle,
uint8_t port,
uint8_t id,
uint32_t type,
uint16_t data_port,
uint16_t cmd_port,
const char *ip) {
connected = _connected;
strncpy(info.broadcast_code, broadcast_code, sizeof(info.broadcast_code));
info.handle = handle;
info.slot = port;
info.id = id;
info.type = type;
info.data_port = data_port;
info.cmd_port = cmd_port;
strncpy(info.ip, ip, sizeof(info.ip));
}
void clear() {
connected = false;
memset(info.broadcast_code, 0, sizeof(info.broadcast_code));
info.handle = 0;
info.slot = 0;
info.id = 0;
info.type = 0;
info.data_port = 0;
info.cmd_port = 0;
memset(info.ip, 0, sizeof(info.ip));
};
} DetailDeviceInfo;
typedef boost::array<DetailDeviceInfo, kMaxConnectedDeviceNum> DeviceContainer;
DeviceContainer devices_;
apr_pool_t *mem_pool_;
DeviceMode device_mode_;
boost::function<void(const DeviceInfo *, DeviceEvent)> connected_cb_;
boost::function<void(const BroadcastDeviceInfo *info)> broadcast_cb_;
boost::mutex mutex_;
};
DeviceManager &device_manager();
void DeviceFound(const DeviceInfo &data);
void DeviceRemove(uint8_t handle);
} // namespace livox
#endif // LIVOX_DEVICE_MANAGER_H_
+98
View File
@@ -0,0 +1,98 @@
//
// The MIT License (MIT)
//
// Copyright (c) 2019 Livox. All rights reserved.
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
// SOFTWARE.
//
#include "livox_sdk.h"
#include "apr_general.h"
#include "command_handler/command_handler.h"
#include "data_handler/data_handler.h"
#include "device_manager.h"
using namespace livox;
IOThread *g_thread = NULL;
bool Init() {
bool result = false;
do {
if (apr_initialize() != APR_SUCCESS) {
result = false;
break;
}
g_thread = new IOThread();
g_thread->Init();
if (device_discovery().Init() == false) {
result = false;
break;
}
if (device_manager().Init() == false) {
result = false;
break;
}
if (command_handler().Init(g_thread->loop()) == false) {
result = false;
break;
}
if (data_handler().Init() == false) {
result = false;
break;
}
result = true;
} while (0);
if (result == false) {
apr_terminate();
}
return result;
}
void Uninit() {
if (g_thread) {
g_thread->Quit();
g_thread->Join();
}
device_discovery().Uninit();
command_handler().Uninit();
data_handler().Uninit();
device_manager().Uninit();
if (g_thread) {
g_thread->Uninit();
delete g_thread;
g_thread = NULL;
}
apr_terminate();
}
bool Start() {
if (g_thread && device_discovery().Start(g_thread->loop()) && g_thread->Start()) {
return true;
}
return false;
}
+241
View File
@@ -0,0 +1,241 @@
/* FastCRC library code is placed under the MIT license
* Copyright (c) 2014,2015 Frank Bosing
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
/*
Tables generated with universal_crc by Danjel McGougan
*/
//
// modify from FastCRC library @ 2018/11/20
//
#ifndef FASTCRC_FASTCRC_TABLES_H_
#define FASTCRC_FASTCRC_TABLES_H_
#include <stdint.h>
// crc16 table
const uint16_t crc_table_mcrf4xx[1024] = {
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78,
0x0000, 0x19d8, 0x33b0, 0x2a68, 0x6760, 0x7eb8, 0x54d0, 0x4d08,
0xcec0, 0xd718, 0xfd70, 0xe4a8, 0xa9a0, 0xb078, 0x9a10, 0x83c8,
0x9591, 0x8c49, 0xa621, 0xbff9, 0xf2f1, 0xeb29, 0xc141, 0xd899,
0x5b51, 0x4289, 0x68e1, 0x7139, 0x3c31, 0x25e9, 0x0f81, 0x1659,
0x2333, 0x3aeb, 0x1083, 0x095b, 0x4453, 0x5d8b, 0x77e3, 0x6e3b,
0xedf3, 0xf42b, 0xde43, 0xc79b, 0x8a93, 0x934b, 0xb923, 0xa0fb,
0xb6a2, 0xaf7a, 0x8512, 0x9cca, 0xd1c2, 0xc81a, 0xe272, 0xfbaa,
0x7862, 0x61ba, 0x4bd2, 0x520a, 0x1f02, 0x06da, 0x2cb2, 0x356a,
0x4666, 0x5fbe, 0x75d6, 0x6c0e, 0x2106, 0x38de, 0x12b6, 0x0b6e,
0x88a6, 0x917e, 0xbb16, 0xa2ce, 0xefc6, 0xf61e, 0xdc76, 0xc5ae,
0xd3f7, 0xca2f, 0xe047, 0xf99f, 0xb497, 0xad4f, 0x8727, 0x9eff,
0x1d37, 0x04ef, 0x2e87, 0x375f, 0x7a57, 0x638f, 0x49e7, 0x503f,
0x6555, 0x7c8d, 0x56e5, 0x4f3d, 0x0235, 0x1bed, 0x3185, 0x285d,
0xab95, 0xb24d, 0x9825, 0x81fd, 0xccf5, 0xd52d, 0xff45, 0xe69d,
0xf0c4, 0xe91c, 0xc374, 0xdaac, 0x97a4, 0x8e7c, 0xa414, 0xbdcc,
0x3e04, 0x27dc, 0x0db4, 0x146c, 0x5964, 0x40bc, 0x6ad4, 0x730c,
0x8ccc, 0x9514, 0xbf7c, 0xa6a4, 0xebac, 0xf274, 0xd81c, 0xc1c4,
0x420c, 0x5bd4, 0x71bc, 0x6864, 0x256c, 0x3cb4, 0x16dc, 0x0f04,
0x195d, 0x0085, 0x2aed, 0x3335, 0x7e3d, 0x67e5, 0x4d8d, 0x5455,
0xd79d, 0xce45, 0xe42d, 0xfdf5, 0xb0fd, 0xa925, 0x834d, 0x9a95,
0xafff, 0xb627, 0x9c4f, 0x8597, 0xc89f, 0xd147, 0xfb2f, 0xe2f7,
0x613f, 0x78e7, 0x528f, 0x4b57, 0x065f, 0x1f87, 0x35ef, 0x2c37,
0x3a6e, 0x23b6, 0x09de, 0x1006, 0x5d0e, 0x44d6, 0x6ebe, 0x7766,
0xf4ae, 0xed76, 0xc71e, 0xdec6, 0x93ce, 0x8a16, 0xa07e, 0xb9a6,
0xcaaa, 0xd372, 0xf91a, 0xe0c2, 0xadca, 0xb412, 0x9e7a, 0x87a2,
0x046a, 0x1db2, 0x37da, 0x2e02, 0x630a, 0x7ad2, 0x50ba, 0x4962,
0x5f3b, 0x46e3, 0x6c8b, 0x7553, 0x385b, 0x2183, 0x0beb, 0x1233,
0x91fb, 0x8823, 0xa24b, 0xbb93, 0xf69b, 0xef43, 0xc52b, 0xdcf3,
0xe999, 0xf041, 0xda29, 0xc3f1, 0x8ef9, 0x9721, 0xbd49, 0xa491,
0x2759, 0x3e81, 0x14e9, 0x0d31, 0x4039, 0x59e1, 0x7389, 0x6a51,
0x7c08, 0x65d0, 0x4fb8, 0x5660, 0x1b68, 0x02b0, 0x28d8, 0x3100,
0xb2c8, 0xab10, 0x8178, 0x98a0, 0xd5a8, 0xcc70, 0xe618, 0xffc0,
0x0000, 0x5adc, 0xb5b8, 0xef64, 0x6361, 0x39bd, 0xd6d9, 0x8c05,
0xc6c2, 0x9c1e, 0x737a, 0x29a6, 0xa5a3, 0xff7f, 0x101b, 0x4ac7,
0x8595, 0xdf49, 0x302d, 0x6af1, 0xe6f4, 0xbc28, 0x534c, 0x0990,
0x4357, 0x198b, 0xf6ef, 0xac33, 0x2036, 0x7aea, 0x958e, 0xcf52,
0x033b, 0x59e7, 0xb683, 0xec5f, 0x605a, 0x3a86, 0xd5e2, 0x8f3e,
0xc5f9, 0x9f25, 0x7041, 0x2a9d, 0xa698, 0xfc44, 0x1320, 0x49fc,
0x86ae, 0xdc72, 0x3316, 0x69ca, 0xe5cf, 0xbf13, 0x5077, 0x0aab,
0x406c, 0x1ab0, 0xf5d4, 0xaf08, 0x230d, 0x79d1, 0x96b5, 0xcc69,
0x0676, 0x5caa, 0xb3ce, 0xe912, 0x6517, 0x3fcb, 0xd0af, 0x8a73,
0xc0b4, 0x9a68, 0x750c, 0x2fd0, 0xa3d5, 0xf909, 0x166d, 0x4cb1,
0x83e3, 0xd93f, 0x365b, 0x6c87, 0xe082, 0xba5e, 0x553a, 0x0fe6,
0x4521, 0x1ffd, 0xf099, 0xaa45, 0x2640, 0x7c9c, 0x93f8, 0xc924,
0x054d, 0x5f91, 0xb0f5, 0xea29, 0x662c, 0x3cf0, 0xd394, 0x8948,
0xc38f, 0x9953, 0x7637, 0x2ceb, 0xa0ee, 0xfa32, 0x1556, 0x4f8a,
0x80d8, 0xda04, 0x3560, 0x6fbc, 0xe3b9, 0xb965, 0x5601, 0x0cdd,
0x461a, 0x1cc6, 0xf3a2, 0xa97e, 0x257b, 0x7fa7, 0x90c3, 0xca1f,
0x0cec, 0x5630, 0xb954, 0xe388, 0x6f8d, 0x3551, 0xda35, 0x80e9,
0xca2e, 0x90f2, 0x7f96, 0x254a, 0xa94f, 0xf393, 0x1cf7, 0x462b,
0x8979, 0xd3a5, 0x3cc1, 0x661d, 0xea18, 0xb0c4, 0x5fa0, 0x057c,
0x4fbb, 0x1567, 0xfa03, 0xa0df, 0x2cda, 0x7606, 0x9962, 0xc3be,
0x0fd7, 0x550b, 0xba6f, 0xe0b3, 0x6cb6, 0x366a, 0xd90e, 0x83d2,
0xc915, 0x93c9, 0x7cad, 0x2671, 0xaa74, 0xf0a8, 0x1fcc, 0x4510,
0x8a42, 0xd09e, 0x3ffa, 0x6526, 0xe923, 0xb3ff, 0x5c9b, 0x0647,
0x4c80, 0x165c, 0xf938, 0xa3e4, 0x2fe1, 0x753d, 0x9a59, 0xc085,
0x0a9a, 0x5046, 0xbf22, 0xe5fe, 0x69fb, 0x3327, 0xdc43, 0x869f,
0xcc58, 0x9684, 0x79e0, 0x233c, 0xaf39, 0xf5e5, 0x1a81, 0x405d,
0x8f0f, 0xd5d3, 0x3ab7, 0x606b, 0xec6e, 0xb6b2, 0x59d6, 0x030a,
0x49cd, 0x1311, 0xfc75, 0xa6a9, 0x2aac, 0x7070, 0x9f14, 0xc5c8,
0x09a1, 0x537d, 0xbc19, 0xe6c5, 0x6ac0, 0x301c, 0xdf78, 0x85a4,
0xcf63, 0x95bf, 0x7adb, 0x2007, 0xac02, 0xf6de, 0x19ba, 0x4366,
0x8c34, 0xd6e8, 0x398c, 0x6350, 0xef55, 0xb589, 0x5aed, 0x0031,
0x4af6, 0x102a, 0xff4e, 0xa592, 0x2997, 0x734b, 0x9c2f, 0xc6f3,
0x0000, 0x1cbb, 0x3976, 0x25cd, 0x72ec, 0x6e57, 0x4b9a, 0x5721,
0xe5d8, 0xf963, 0xdcae, 0xc015, 0x9734, 0x8b8f, 0xae42, 0xb2f9,
0xc3a1, 0xdf1a, 0xfad7, 0xe66c, 0xb14d, 0xadf6, 0x883b, 0x9480,
0x2679, 0x3ac2, 0x1f0f, 0x03b4, 0x5495, 0x482e, 0x6de3, 0x7158,
0x8f53, 0x93e8, 0xb625, 0xaa9e, 0xfdbf, 0xe104, 0xc4c9, 0xd872,
0x6a8b, 0x7630, 0x53fd, 0x4f46, 0x1867, 0x04dc, 0x2111, 0x3daa,
0x4cf2, 0x5049, 0x7584, 0x693f, 0x3e1e, 0x22a5, 0x0768, 0x1bd3,
0xa92a, 0xb591, 0x905c, 0x8ce7, 0xdbc6, 0xc77d, 0xe2b0, 0xfe0b,
0x16b7, 0x0a0c, 0x2fc1, 0x337a, 0x645b, 0x78e0, 0x5d2d, 0x4196,
0xf36f, 0xefd4, 0xca19, 0xd6a2, 0x8183, 0x9d38, 0xb8f5, 0xa44e,
0xd516, 0xc9ad, 0xec60, 0xf0db, 0xa7fa, 0xbb41, 0x9e8c, 0x8237,
0x30ce, 0x2c75, 0x09b8, 0x1503, 0x4222, 0x5e99, 0x7b54, 0x67ef,
0x99e4, 0x855f, 0xa092, 0xbc29, 0xeb08, 0xf7b3, 0xd27e, 0xcec5,
0x7c3c, 0x6087, 0x454a, 0x59f1, 0x0ed0, 0x126b, 0x37a6, 0x2b1d,
0x5a45, 0x46fe, 0x6333, 0x7f88, 0x28a9, 0x3412, 0x11df, 0x0d64,
0xbf9d, 0xa326, 0x86eb, 0x9a50, 0xcd71, 0xd1ca, 0xf407, 0xe8bc,
0x2d6e, 0x31d5, 0x1418, 0x08a3, 0x5f82, 0x4339, 0x66f4, 0x7a4f,
0xc8b6, 0xd40d, 0xf1c0, 0xed7b, 0xba5a, 0xa6e1, 0x832c, 0x9f97,
0xeecf, 0xf274, 0xd7b9, 0xcb02, 0x9c23, 0x8098, 0xa555, 0xb9ee,
0x0b17, 0x17ac, 0x3261, 0x2eda, 0x79fb, 0x6540, 0x408d, 0x5c36,
0xa23d, 0xbe86, 0x9b4b, 0x87f0, 0xd0d1, 0xcc6a, 0xe9a7, 0xf51c,
0x47e5, 0x5b5e, 0x7e93, 0x6228, 0x3509, 0x29b2, 0x0c7f, 0x10c4,
0x619c, 0x7d27, 0x58ea, 0x4451, 0x1370, 0x0fcb, 0x2a06, 0x36bd,
0x8444, 0x98ff, 0xbd32, 0xa189, 0xf6a8, 0xea13, 0xcfde, 0xd365,
0x3bd9, 0x2762, 0x02af, 0x1e14, 0x4935, 0x558e, 0x7043, 0x6cf8,
0xde01, 0xc2ba, 0xe777, 0xfbcc, 0xaced, 0xb056, 0x959b, 0x8920,
0xf878, 0xe4c3, 0xc10e, 0xddb5, 0x8a94, 0x962f, 0xb3e2, 0xaf59,
0x1da0, 0x011b, 0x24d6, 0x386d, 0x6f4c, 0x73f7, 0x563a, 0x4a81,
0xb48a, 0xa831, 0x8dfc, 0x9147, 0xc666, 0xdadd, 0xff10, 0xe3ab,
0x5152, 0x4de9, 0x6824, 0x749f, 0x23be, 0x3f05, 0x1ac8, 0x0673,
0x772b, 0x6b90, 0x4e5d, 0x52e6, 0x05c7, 0x197c, 0x3cb1, 0x200a,
0x92f3, 0x8e48, 0xab85, 0xb73e, 0xe01f, 0xfca4, 0xd969, 0xc5d2
};
// crc32 table
const uint32_t crc_table_crc32[256] = {
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
#endif
+154
View File
@@ -0,0 +1,154 @@
/* FastCRC library code is placed under the MIT license
* Copyright (c) 2014,2015,2016 Frank Bosing
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
//
// Thanks to:
// - Catalogue of parametrised CRC algorithms, CRC RevEng
// http://reveng.sourceforge.net/crc-catalogue/
//
// - Danjel McGougan (CRC-Table-Generator)
//
//
// modify from FastCRC library @ 2018/11/20
//
#include "../include/third_party/FastCRC/FastCRC.h"
#include "FastCRC_tables.hpp"
// ================= 16-BIT CRC ===================
/** Constructor
*/
FastCRC16::FastCRC16(uint16_t seed) {
seed_ = seed;
}
#define crc_n4(crc, data, table) crc ^= data; \
crc = (table[(crc & 0xff) + 0x300]) ^ \
(table[((crc >> 8) & 0xff) + 0x200]) ^ \
(table[((data >> 16) & 0xff) + 0x100]) ^ \
(table[data >> 24]);
/** MCRF4XX
* equivalent to _crc_ccitt_update() in crc16.h from avr_libc
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
uint16_t FastCRC16::mcrf4xx_calc(const uint8_t *data, uint16_t len) {
uint16_t crc = seed_;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ crc_table_mcrf4xx[(crc & 0xff) ^ *data++];
len--;
}
while (len >= 16) {
len -= 16;
crc_n4(crc, ((uint32_t *)data)[0], crc_table_mcrf4xx);
crc_n4(crc, ((uint32_t *)data)[1], crc_table_mcrf4xx);
crc_n4(crc, ((uint32_t *)data)[2], crc_table_mcrf4xx);
crc_n4(crc, ((uint32_t *)data)[3], crc_table_mcrf4xx);
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ crc_table_mcrf4xx[(crc & 0xff) ^ *data++];
}
//seed = crc;
return crc;
}
// ================= 32-BIT CRC ===================
/** Constructor
*/
FastCRC32::FastCRC32(uint32_t seed) {
seed_ = seed;
}
#define crc_n4d(crc, data, table) crc ^= data; \
crc = (table[(crc & 0xff) + 0x300]) ^ \
(table[((crc >> 8) & 0xff) + 0x200]) ^ \
(table[((crc >> 16) & 0xff) + 0x100]) ^ \
(table[(crc >> 24) & 0xff]);
#define crcsm_n4d(crc, data, table) crc ^= data; \
crc = (crc >> 8) ^ (table[crc & 0xff]); \
crc = (crc >> 8) ^ (table[crc & 0xff]); \
crc = (crc >> 8) ^ (table[crc & 0xff]); \
crc = (crc >> 8) ^ (table[crc & 0xff]);
/** CRC32
* Alias CRC-32/ADCCP, PKZIP, Ethernet, 802.3
* @param data Pointer to Data
* @param datalen Length of Data
* @return CRC value
*/
#if CRC_BIGTABLES
#define CRC_TABLE_CRC32 crc_table_crc32_big
#else
#define CRC_TABLE_CRC32 crc_table_crc32
#endif
uint32_t FastCRC32::crc32_calc(const uint8_t *data, uint16_t len) {
uint32_t crc = seed_^0xffffffff;
while (((uintptr_t)data & 3) && len) {
crc = (crc >> 8) ^ CRC_TABLE_CRC32[(crc & 0xff) ^ *data++];
len--;
}
while (len >= 16) {
len -= 16;
#if CRC_BIGTABLES
crc_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CRC32);
crc_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CRC32);
crc_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CRC32);
crc_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CRC32);
#else
crcsm_n4d(crc, ((uint32_t *)data)[0], CRC_TABLE_CRC32);
crcsm_n4d(crc, ((uint32_t *)data)[1], CRC_TABLE_CRC32);
crcsm_n4d(crc, ((uint32_t *)data)[2], CRC_TABLE_CRC32);
crcsm_n4d(crc, ((uint32_t *)data)[3], CRC_TABLE_CRC32);
#endif
data += 16;
}
while (len--) {
crc = (crc >> 8) ^ CRC_TABLE_CRC32[(crc & 0xff) ^ *data++];
}
//seed = crc;
crc ^= 0xffffffff;
return crc;
}
+21
View File
@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2016 Frank
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+56
View File
@@ -0,0 +1,56 @@
FastCRC
=======
Fast CRC Arduino library
Up to 30 times faster than crc16.h (_avr_libc)
- uses the on-chip hardware for Teensy 3.0 / 3.1 / 3.2 / 3.5 / 3.6
- uses fast table-algorithms for other chips
List of supported CRC calculations:
-
7 BIT:
CRC7
(poly=0x09 init=0x00 refin=false refout=false xorout=0x00 check=0x75)
MultiMediaCard interface
8 BIT:
SMBUS
(poly=0x07 init=0x00 refin=false refout=false xorout=0x00 check=0xf4)
MAXIM
(poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xa1)
16 BIT:
KERMIT (Alias CRC-16/CCITT, CRC-16/CCITT-TRUE, CRC-CCITT)
(poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 check=0x2189
Attention: sometimes you'll find byteswapped presentation of result in other implementations)
CCITT-FALSE
(poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1)
MCRF4XX
(poly=0x1021 init=0xffff refin=true refout=true xorout=0x0000 check=0x6f91)
MODBUS
(poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37)
XMODEM (Alias ZMODEM, CRC-16/ACORN)
(poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 check=0x31c3)
X25 (Alias CRC-16/IBM-SDLC, CRC-16/ISO-HDLC, CRC-B)
(poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff check=0x906e)
32 BIT:
CRC32, CRC-32/ADCCP, PKZIP, ETHERNET, 802.3
(poly=0x04c11db7 init=0xffffffff refin=true refout=true xorout=0xffffffff check=0xcbf43926)
CKSUM, CRC-32/POSIX
(poly=0x04c11db7 init=0x00000000 refin=false refout=false xorout=0xffffffff check=0x765e7680)