diff --git a/aether/CMakeLists.txt b/aether/CMakeLists.txt index 74bb93eb..c4bee1ea 100644 --- a/aether/CMakeLists.txt +++ b/aether/CMakeLists.txt @@ -36,8 +36,7 @@ list(APPEND common_dependencies "../third_party/libsodium" "../third_party/gcem" "../third_party/etl" - "../third_party/aethernet-numeric" -) + "../third_party/aethernet-numeric") # for etl set(GIT_DIR_LOOKUP_POLICY ALLOW_LOOKING_ABOVE_CMAKE_SOURCE_DIR) @@ -56,8 +55,7 @@ list(APPEND aether_srcs list(APPEND aether_c_api_srcs "aether_c/c_uid.cpp" - "aether_c/aether_capi.cpp" -) + "aether_c/aether_capi.cpp") list(APPEND types_srcs "types/address.cpp") @@ -85,14 +83,12 @@ list(APPEND obj_srcs "obj/domain.cpp" "obj/obj_id.cpp" "obj/registry.cpp" - "obj/obj_ptr.cpp" - ) + "obj/obj_ptr.cpp") list(APPEND ptr_srcs "ptr/ptr.cpp" "ptr/ptr_view.cpp" - "ptr/ref_tree.cpp" - ) + "ptr/ref_tree.cpp") list(APPEND actions_srcs "ae_actions/get_client_cloud.cpp" @@ -106,8 +102,7 @@ list(APPEND actions_srcs "actions/action_processor.cpp" "actions/timer_action.cpp" "actions/task_queue.cpp" - "actions/repeatable_task.cpp" - ) + "actions/repeatable_task.cpp") list(APPEND registration_srcs "registration/api/client_reg_api_safe.cpp" @@ -131,8 +126,7 @@ list(APPEND adapters_srcs "adapters/modem_adapter.cpp" "adapters/parent_lora_module.cpp" "adapters/parent_modem.cpp" - "adapters/parent_wifi.cpp" - ) + "adapters/parent_wifi.cpp") list(APPEND access_points_srcs "access_points/access_point.cpp" @@ -150,6 +144,7 @@ list(APPEND modems_srcs list(APPEND lora_modules_srcs "lora_modules/dx_smart_lr02_lm.cpp" "lora_modules/ebyte_e22_lm.cpp" + "lora_modules/gw_lora_device.cpp" "lora_modules/lora_module_factory.cpp") list(APPEND gateway_api_srcs @@ -157,8 +152,7 @@ list(APPEND gateway_api_srcs list(APPEND wifi_srcs "wifi/wifi_driver_factory.cpp" - "wifi/esp_wifi_driver.cpp" - ) + "wifi/esp_wifi_driver.cpp") list(APPEND serial_ports_srcs "serial_ports/at_support/at_buffer.cpp" @@ -169,8 +163,7 @@ list(APPEND serial_ports_srcs "serial_ports/serial_port_factory.cpp" "serial_ports/esp32_serial_port.cpp" "serial_ports/win_serial_port.cpp" - "serial_ports/unix_serial_port.cpp" - ) + "serial_ports/unix_serial_port.cpp") list(APPEND transport_srcs "transport/system_sockets/sockets/unix_socket.cpp" @@ -189,8 +182,7 @@ list(APPEND transport_srcs "transport/system_sockets/tcp/tcp.cpp" "transport/system_sockets/udp/udp.cpp" "transport/modems/modem_transport.cpp" - "transport/gateway/gateway_transport.cpp" -) + "transport/gateway/gateway_transport.cpp") list(APPEND stream_api_src "stream_api/stream_write_action.cpp" @@ -206,15 +198,13 @@ list(APPEND stream_api_src "stream_api/safe_stream/sending_chunk_list.cpp" "stream_api/safe_stream/receiving_chunk_list.cpp" "stream_api/safe_stream/safe_stream_send_action.cpp" - "stream_api/safe_stream/safe_stream_recv_action.cpp" -) + "stream_api/safe_stream/safe_stream_recv_action.cpp") list(APPEND api_protocol_srcs "api_protocol/protocol_context.cpp" "api_protocol/api_pack_parser.cpp" "api_protocol/child_data.cpp" - "api_protocol/return_result_api.cpp" - ) + "api_protocol/return_result_api.cpp") list(APPEND crypto_srcs "crypto/crypto_nonce.cpp" @@ -225,8 +215,7 @@ list(APPEND crypto_srcs "crypto/sodium/sodium_async_crypto_provider.cpp" "crypto/sodium/sodium_sync_crypto_provider.cpp" "crypto/hydrogen/hydro_async_crypto_provider.cpp" - "crypto/hydrogen/hydro_sync_crypto_provider.cpp" - ) + "crypto/hydrogen/hydro_sync_crypto_provider.cpp") list(APPEND work_cloud_api_srcs "work_cloud_api/work_server_api/login_api.cpp" diff --git a/aether/access_points/lora_module_access_point.cpp b/aether/access_points/lora_module_access_point.cpp index 21ef9b41..16ead431 100644 --- a/aether/access_points/lora_module_access_point.cpp +++ b/aether/access_points/lora_module_access_point.cpp @@ -15,17 +15,19 @@ */ #include "aether/access_points/lora_module_access_point.h" -#if AE_SUPPORT_LORA + +#if AE_SUPPORT_LORA && AE_SUPPORT_GATEWAY # include "aether/aether.h" +# include "aether/server.h" # include "aether/lora_modules/ilora_module_driver.h" # include "aether/channels/lora_module_channel.h" # include "aether/access_points/filter_protocols.h" namespace ae { -LoraModuleConnectAction::LoraModuleConnectAction( - ActionContext action_context, [[maybe_unused]] ILoraModuleDriver& driver) +LoraModuleConnectAction::LoraModuleConnectAction(ActionContext action_context, + [[maybe_unused]] ILoraModuleDriver& driver) : Action{action_context}, driver_{&driver}, state_{State::kStart} { AE_TELED_DEBUG("LoraModuleConnectAction created"); } @@ -67,6 +69,13 @@ void LoraModuleConnectAction::Start() { }); } +LoraModuleAccessPoint::JoinAction::JoinAction(ActionContext action_context) + : Action{action_context} {} + +UpdateStatus LoraModuleAccessPoint::JoinAction::Update() { + return UpdateStatus::Result(); +} + LoraModuleAccessPoint::LoraModuleAccessPoint( ObjPtr aether, LoraModuleAdapter::ptr lora_module_adapter, Domain* domain) @@ -91,21 +100,25 @@ ILoraModuleDriver& LoraModuleAccessPoint::lora_module_driver() { return lora_module_adapter_->lora_module_driver(); } +ActionPtr LoraModuleAccessPoint::Join() { + return ActionPtr{*aether_}; +} + std::vector> LoraModuleAccessPoint::GenerateChannels( - std::vector const& endpoints) { + ObjPtr const& server) { AE_TELED_DEBUG("Generate lora module channels"); - std::vector> channels; - channels.reserve(endpoints.size()); - Aether::ptr aether = aether_; - LoraModuleAccessPoint::ptr self = MakePtrFromThis(this); - for (auto const& endpoint : endpoints) { - if (!FilterProtocol(endpoint)) { - continue; - } - channels.emplace_back( - domain_->CreateObj(aether, self, endpoint)); + auto self_ptr = MakePtrFromThis(this); + return {domain_->CreateObj(self_ptr, server)}; +} + +Aether::ptr const& LoraModuleAccessPoint::aether() const { return aether_; } + +GwLoraDevice& LoraModuleAccessPoint::gw_lora_device() { + if (!gw_lora_device_) { + gw_lora_device_ = std::make_unique( + *aether_); } - return channels; + return *gw_lora_device_; } } // namespace ae diff --git a/aether/access_points/lora_module_access_point.h b/aether/access_points/lora_module_access_point.h index 46b0d506..d82c321d 100644 --- a/aether/access_points/lora_module_access_point.h +++ b/aether/access_points/lora_module_access_point.h @@ -19,15 +19,14 @@ #include "aether/config.h" -#if AE_SUPPORT_LORA +#if AE_SUPPORT_LORA && AE_SUPPORT_GATEWAY + # include "aether/obj/obj.h" # include "aether/actions/action.h" # include "aether/actions/action_ptr.h" -# include "aether/types/state_machine.h" -# include "aether/lora_modules/ilora_module_driver.h" # include "aether/adapters/lora_module_adapter.h" -# include "aether/events/event_subscription.h" # include "aether/access_points/access_point.h" +# include "aether/lora_modules/gw_lora_device.h" namespace ae { class Aether; @@ -40,8 +39,7 @@ class LoraModuleConnectAction final : public Action { kFailed, }; - LoraModuleConnectAction(ActionContext action_context, - ILoraModuleDriver& driver); + LoraModuleConnectAction(ActionContext action_context, ILoraModuleDriver& driver); UpdateStatus Update(); @@ -58,23 +56,35 @@ class LoraModuleAccessPoint final : public AccessPoint { LoraModuleAccessPoint() = default; public: + class JoinAction : public Action { + public: + explicit JoinAction(ActionContext action_context); + UpdateStatus Update(); + }; + LoraModuleAccessPoint(ObjPtr aether, LoraModuleAdapter::ptr lora_module_adapter, Domain* domain); - AE_OBJECT_REFLECT(AE_MMBRS(aether_, lora_module_adapter_)); + AE_OBJECT_REFLECT(AE_MMBRS(lora_module_adapter_)); ActionPtr Connect(); ILoraModuleDriver& lora_module_driver(); + + ActionPtr Join(); std::vector> GenerateChannels( - std::vector const& endpoints) override; + Server::ptr const& server) override; + + Aether::ptr const& aether() const; + GwLoraDevice& gw_lora_device(); private: - Obj::ptr aether_; + Aether::ptr aether_; LoraModuleAdapter::ptr lora_module_adapter_; ActionPtr connect_action_; Subscription connect_sub_; + std::unique_ptr gw_lora_device_; }; } // namespace ae #endif diff --git a/aether/adapters/lora_module_adapter.cpp b/aether/adapters/lora_module_adapter.cpp index bcb4d97a..92bcf09e 100644 --- a/aether/adapters/lora_module_adapter.cpp +++ b/aether/adapters/lora_module_adapter.cpp @@ -15,7 +15,8 @@ */ #include "aether/adapters/lora_module_adapter.h" -#if AE_SUPPORT_LORA + +#if AE_SUPPORT_LORA && AE_SUPPORT_GATEWAY # include "aether/aether.h" # include "aether/lora_modules/lora_module_factory.h" diff --git a/aether/adapters/lora_module_adapter.h b/aether/adapters/lora_module_adapter.h index 7b95b1e6..1874ea5a 100644 --- a/aether/adapters/lora_module_adapter.h +++ b/aether/adapters/lora_module_adapter.h @@ -17,21 +17,19 @@ #ifndef AETHER_ADAPTERS_LORA_MODULE_ADAPTER_H_ #define AETHER_ADAPTERS_LORA_MODULE_ADAPTER_H_ -#include "aether/config.h" +#include -#if AE_SUPPORT_LORA -# include +#include "aether/config.h" +#if AE_SUPPORT_LORA && AE_SUPPORT_GATEWAY # include "aether/events/events.h" # include "aether/lora_modules/ilora_module_driver.h" # include "aether/adapters/parent_lora_module.h" # include "aether/access_points/access_point.h" -# define LORA_MODULE_TCP_TRANSPORT_ENABLED 1 - namespace ae { -class LoraModuleAdapter : public ParentLoraModuleAdapter { +class LoraModuleAdapter final : public ParentLoraModuleAdapter { AE_OBJECT(LoraModuleAdapter, ParentLoraModuleAdapter, 0) LoraModuleAdapter() = default; diff --git a/aether/adapters/parent_lora_module.h b/aether/adapters/parent_lora_module.h index 56a25390..7888b3ec 100644 --- a/aether/adapters/parent_lora_module.h +++ b/aether/adapters/parent_lora_module.h @@ -19,7 +19,8 @@ #include "aether/config.h" -#if AE_SUPPORT_LORA +#if AE_SUPPORT_LORA && AE_SUPPORT_GATEWAY + # include "aether/aether.h" # include "aether/adapters/adapter.h" # include "aether/lora_modules/lora_module_driver_types.h" @@ -47,5 +48,6 @@ class ParentLoraModuleAdapter : public Adapter { LoraModuleInit lora_module_init_; }; } // namespace ae + #endif #endif // AETHER_ADAPTERS_PARENT_LORA_MODULE_H_ diff --git a/aether/channels/lora_module_channel.cpp b/aether/channels/lora_module_channel.cpp index 05b22bb5..59dd997c 100644 --- a/aether/channels/lora_module_channel.cpp +++ b/aether/channels/lora_module_channel.cpp @@ -15,59 +15,58 @@ */ #include "aether/channels/lora_module_channel.h" -#if AE_SUPPORT_LORA + +#if AE_SUPPORT_LORA && AE_SUPPORT_GATEWAY # include # include "aether/memory.h" # include "aether/aether.h" # include "aether/types/state_machine.h" -# include "aether/transport/lora_modules/lora_module_transport.h" +# include "aether/transport/gateway/gateway_transport.h" namespace ae { namespace lora_module_channel_internal { class LoraModuleTransportBuilderAction final : public TransportBuilderAction { enum class State : std::uint8_t { - kLoraModuleConnect, + kMLoraModuleConnect, + kJoin, kTransportCreate, - kWaitTransportConnected, - kTransportConnected, - kFailed + kResult, + kError }; public: LoraModuleTransportBuilderAction(ActionContext action_context, - LoraModuleChannel& channel, LoraModuleAccessPoint& access_point, - Endpoint address) + Server::ptr const& server) : TransportBuilderAction{action_context}, action_context_{action_context}, - channel_{&channel}, access_point_{&access_point}, - address_{std::move(address)}, - state_{State::kLoraModuleConnect}, - start_time_{Now()} { + server_{server}, + state_{State::kMLoraModuleConnect} { AE_TELED_DEBUG("Lora module transport building"); + state_.changed_event().Subscribe([this](auto) { Action::Trigger(); }); } UpdateStatus Update() override { if (state_.changed()) { switch (state_.Acquire()) { - case State::kLoraModuleConnect: + case State::kMLoraModuleConnect: ConnectLoraModule(); break; + case State::kJoin: + Join(); + break; case State::kTransportCreate: CreateTransport(); break; - case State::kWaitTransportConnected: - break; - case State::kTransportConnected: + case State::kResult: return UpdateStatus::Result(); - case State::kFailed: + case State::kError: return UpdateStatus::Error(); } } - return {}; } @@ -77,104 +76,68 @@ class LoraModuleTransportBuilderAction final : public TransportBuilderAction { private: void ConnectLoraModule() { - lora_module_connect_sub_ = + modem_connect_sub_ = access_point_->Connect()->StatusEvent().Subscribe(ActionHandler{ OnResult{[this]() { state_ = State::kTransportCreate; Action::Trigger(); }}, OnError{[this]() { - state_ = State::kFailed; + state_ = State::kError; Action::Trigger(); }}, }); } - void CreateTransport() { - state_ = State::kWaitTransportConnected; - - auto& lora_module_driver = access_point_->lora_module_driver(); - transport_stream_ = std::make_unique( - action_context_, lora_module_driver, address_); - - if (transport_stream_->stream_info().link_state == LinkState::kLinked) { - Connected(); - return; - } - - tranpsport_sub_ = - transport_stream_->stream_update_event().Subscribe([this]() { - if (transport_stream_->stream_info().link_state == - LinkState::kLinked) { - Connected(); - } else if (transport_stream_->stream_info().link_state == - LinkState::kLinkError) { - state_ = State::kFailed; - Action::Trigger(); - } - }); + void Join() { + auto join = access_point_->Join(); + join->StatusEvent().Subscribe(ActionHandler{ + OnResult{[this]() { state_ = State::kTransportCreate; }}, + OnError{[this]() { state_ = State::kError; }}, + }); } - void Connected() { - auto built_time = std::chrono::duration_cast(Now() - start_time_); - AE_TELED_DEBUG("Lora modem transport built by {:%S}", built_time); - channel_->channel_statistics().AddConnectionTime(built_time); - state_ = State::kTransportConnected; - Action::Trigger(); + void CreateTransport() { + auto server = server_.Lock(); + assert(server && "Server should be alive"); + + if (server->server_id == 0) { + transport_stream_ = std::make_unique( + ServerEndpoints{server->endpoints}, access_point_->gw_lora_device()); + } else { + transport_stream_ = std::make_unique( + server->server_id, access_point_->gw_lora_device()); + } + state_ = State::kResult; } ActionContext action_context_; - LoraModuleChannel* channel_; LoraModuleAccessPoint* access_point_; - Endpoint address_; + PtrView server_; StateMachine state_; - std::unique_ptr transport_stream_; - Subscription tranpsport_sub_; - Subscription lora_module_connect_sub_; - TimePoint start_time_; + + std::unique_ptr transport_stream_; + Subscription modem_connect_sub_; }; } // namespace lora_module_channel_internal -LoraModuleChannel::LoraModuleChannel(ObjPtr aether, - LoraModuleAccessPoint::ptr access_point, - Endpoint address, Domain* domain) - : Channel{std::move(address), domain}, - aether_{std::move(aether)}, - access_point_{std::move(access_point)} { - // fill transport properties - transport_properties_.max_packet_size = 400; +LoraModuleChannel::LoraModuleChannel(LoraModuleAccessPoint::ptr access_point, + Server::ptr server, Domain* domain) + : Channel{domain}, + access_point_{std::move(access_point)}, + server_{std::move(server)} { + transport_properties_.connection_type = ConnectionType::kConnectionLess; + transport_properties_.reliability = Reliability::kUnreliable; transport_properties_.rec_packet_size = 400; - auto protocol = std::visit([](auto&& adr) { return adr.protocol; }, address); - switch (protocol) { - case Protocol::kTcp: { - transport_properties_.connection_type = ConnectionType::kConnectionFull; - transport_properties_.reliability = Reliability::kReliable; - break; - } - case Protocol::kUdp: { - transport_properties_.connection_type = ConnectionType::kConnectionLess; - transport_properties_.reliability = Reliability::kUnreliable; - break; - } - default: - // protocol is not supported - assert(false); - } + transport_properties_.max_packet_size = 400; } ActionPtr LoraModuleChannel::TransportBuilder() { - if (!access_point_) { - aether_->domain_->LoadRoot(access_point_); - } + auto const& aether = access_point_->aether(); return ActionPtr< lora_module_channel_internal::LoraModuleTransportBuilderAction>{ - *aether_.as(), *this, *access_point_, address}; -} - -Duration LoraModuleChannel::TransportBuildTimeout() const { - return channel_statistics_->connection_time_statistics().percentile<99>() + - std::chrono::seconds{5}; + *aether, *access_point_, server_}; } } // namespace ae diff --git a/aether/channels/lora_module_channel.h b/aether/channels/lora_module_channel.h index b8812007..d0a9448e 100644 --- a/aether/channels/lora_module_channel.h +++ b/aether/channels/lora_module_channel.h @@ -19,31 +19,29 @@ #include "aether/config.h" -#if AE_SUPPORT_LORA +#if AE_SUPPORT_LORA && AE_SUPPORT_GATEWAY + # include "aether/channels/channel.h" # include "aether/access_points/lora_module_access_point.h" namespace ae { -class Aether; - class LoraModuleChannel final : public Channel { AE_OBJECT(LoraModuleChannel, Channel, 0) LoraModuleChannel() = default; public: - LoraModuleChannel(ObjPtr aether, - LoraModuleAccessPoint::ptr access_point, Endpoint address, + LoraModuleChannel(LoraModuleAccessPoint::ptr access_point, Server::ptr server, Domain* domain); AE_OBJECT_REFLECT(AE_MMBRS(access_point_)) ActionPtr TransportBuilder() override; - Duration TransportBuildTimeout() const override; + Endpoint address; private: - Obj::ptr aether_; LoraModuleAccessPoint::ptr access_point_; + Server::ptr server_; }; } // namespace ae #endif diff --git a/aether/config.h b/aether/config.h index b06cd135..8b3019c2 100644 --- a/aether/config.h +++ b/aether/config.h @@ -207,7 +207,7 @@ #endif // default value used for connection timeout, until statistics are available #ifndef AE_DEFAULT_CONNECTION_TIMEOUT_MS -# define AE_DEFAULT_CONNECTION_TIMEOUT_MS 5000 +# define AE_DEFAULT_CONNECTION_TIMEOUT_MS 15000 #endif // window size for server answear to ping statistics diff --git a/aether/lora_modules/dx_smart_lr02_lm.cpp b/aether/lora_modules/dx_smart_lr02_lm.cpp index ca6d64e1..d22b861e 100644 --- a/aether/lora_modules/dx_smart_lr02_lm.cpp +++ b/aether/lora_modules/dx_smart_lr02_lm.cpp @@ -38,57 +38,17 @@ static const AtRequest::Wait kWaitEntryAt{"Entry AT", kOneSecond}; static const AtRequest::Wait kWaitExitAt{"Exit AT", kOneSecond}; static const AtRequest::Wait kWaitPowerOn{"Power on", kOneSecond}; -class DxSmartLr02TcpOpenNetwork final - : public Action { + class DxSmartLr02LoraOpenNetwork final + : public Action { public: - DxSmartLr02TcpOpenNetwork(ActionContext action_context, - DxSmartLr02LoraModule& /* lora_module */, - std::string host, std::uint16_t port) + DxSmartLr02LoraOpenNetwork(ActionContext action_context, + DxSmartLr02LoraModule& /* lora_module */, + std::string host, std::uint16_t port) : Action{action_context}, action_context_{action_context}, host_{std::move(host)}, port_{port} { - AE_TELED_DEBUG("Open tcp connection for {}:{}", host_, port_); - } - - UpdateStatus Update() const { - if (success_) { - return UpdateStatus::Result(); - } - if (error_) { - return UpdateStatus::Error(); - } - if (stop_) { - return UpdateStatus::Stop(); - } - return {}; - } - - ConnectionLoraIndex connection_index() const { return connection_index_; } - - private: - ActionContext action_context_; - std::string host_; - std::uint16_t port_; - ActionPtr operation_pipeline_; - Subscription operation_sub_; - ConnectionLoraIndex connection_index_ = kInvalidConnectionLoraIndex; - bool success_{}; - bool error_{}; - bool stop_{}; -}; - -class DxSmartLr02UdpOpenNetwork final - : public Action { - public: - DxSmartLr02UdpOpenNetwork(ActionContext action_context, - DxSmartLr02LoraModule& /* lora_module */, - std::string host, std::uint16_t port) - : Action{action_context}, - action_context_{action_context}, - host_{std::move(host)}, - port_{port} { - AE_TELED_DEBUG("Open UDP connection for {}:{}", host_, port_); + AE_TELED_DEBUG("Open lora connection for {}:{}", host_, port_); } UpdateStatus Update() const { @@ -125,11 +85,14 @@ DxSmartLr02LoraModule::DxSmartLr02LoraModule(ActionContext action_context, lora_module_init_{std::move(lora_module_init)}, serial_{SerialPortFactory::CreatePort(action_context_, poller, lora_module_init_.serial_init)}, - at_comm_support_{action_context_, *serial_}, + at_support_{action_context_, *serial_}, operation_queue_{action_context_}, initiated_{false}, started_{false} { + serial_->read_event().Subscribe( + MethodPtr<&DxSmartLr02LoraModule::ReadPacket>{this}); Init(); + Start(); } DxSmartLr02LoraModule::~DxSmartLr02LoraModule() { Stop(); } @@ -151,14 +114,10 @@ DxSmartLr02LoraModule::Start() { auto pipeline = MakeActionPtr(action_context_, - // Enter AT command mode - Stage([this]() { return EnterAtMode(); }), - // Exit AT command mode - Stage([this]() { return ExitAtMode(); }), // save it's started Stage(action_context_, [this]() { started_ = true; - SetupPoll(); + // SetupPoll(); return UpdateStatus::Result(); })); @@ -183,7 +142,7 @@ DxSmartLr02LoraModule::Stop() { action_context_, // Enter AT command mode Stage([this]() { return EnterAtMode(); }), Stage([this]() { - return at_comm_support_.MakeRequest("AT+RESET", kWaitOk); + return at_support_.MakeRequest("AT+RESET", kWaitOk); }), // Exit AT command mode Stage([this]() { return ExitAtMode(); })); @@ -200,89 +159,31 @@ DxSmartLr02LoraModule::Stop() { return lora_module_operation; } -ActionPtr -DxSmartLr02LoraModule::OpenNetwork(ae::Protocol protocol, - std::string const& host, - std::uint16_t port) { - auto open_network_operation = - ActionPtr{action_context_}; - - operation_queue_->Push(Stage([this, open_network_operation, protocol, - host{host}, port]() -> ActionPtr { - if (protocol == Protocol::kTcp) { - return OpenTcpConnection(open_network_operation, host, port); - } - if (protocol == Protocol::kUdp) { - return OpenUdpConnection(open_network_operation, host, port); - } +ActionPtr +DxSmartLr02LoraModule::WritePacket(ae::ConnectionLoraIndex connect_index, + ae::DataBuffer const& data) { + if (data.size() > kLoraModuleMTU) { + assert(false); return {}; - })); + } - return open_network_operation; -} + auto write_notify = ActionPtr{action_context_}; -ActionPtr -DxSmartLr02LoraModule::CloseNetwork(ae::ConnectionLoraIndex /*connect_index*/) { - return {}; -} -// void DxSmartLr02LoraModule::CloseNetwork( -// ae::ConnectionLoraIndex connect_index) { -// if (connect_index >= connect_vec_.size()) { -// AE_TELED_ERROR("Connection index overflow"); -// return; -// } -// -// connect_vec_.erase(connect_vec_.begin() + connect_index); -//}; + AE_TELED_DEBUG("Queue write packet for data size {}", data.size()); -ActionPtr -DxSmartLr02LoraModule::WritePacket(ae::ConnectionLoraIndex /*connect_index*/, - ae::DataBuffer const& /*data*/) { - return {}; -} -// void DxSmartLr02LoraModule::WritePacket( -// ae::ConnectionLoraIndex connect_index, -// ae::DataBuffer const& data) { -// LoraPacket lora_packet{}; -// -// auto const& connection = -// connect_vec_.at(static_cast(connect_index)); -// -// lora_packet.connection = connection; -// lora_packet.length = data.size(); -// lora_packet.data = data; -// lora_packet.crc = 0; // Not implemented yet -// -// auto packet_data = std::vector{}; -// VectorWriter vw{packet_data}; -// auto os = omstream{vw}; -// // copy data with size -// os << lora_packet; -// -// serial_->Write(packet_data); -//}; - -ActionPtr DxSmartLr02LoraModule::ReadPacket( - ConnectionLoraIndex /* connection */) { - return {}; -} + operation_queue_->Push( + Stage([this, write_notify, connect_index, data{data}]() { + auto write_pipeline = SendData(connect_index, data); + write_pipeline->StatusEvent().Subscribe(ActionHandler{ + OnResult{[write_notify]() { write_notify->Notify(); }}, + OnError{[write_notify]() { write_notify->Failed(); }}, + OnStop{[write_notify]() { write_notify->Stop(); }}, + }); + return write_pipeline; + })); -// DataBuffer DxSmartLr02LoraModule::ReadPacket( -// ae::ConnectionLoraIndex /* connect_index*/, ae::Duration /* timeout*/) { -// LoraPacket lora_packet{}; -// DataBuffer data{}; -// -// auto response = serial_->Read(); -// std::vector packet_data(response->begin(), response->end()); -// VectorReader vr(packet_data); -// auto is = imstream{vr}; -// // copy data with size -// is >> lora_packet; -// -// data = lora_packet.data; -// -// return data; -// }; + return write_notify; +} DxSmartLr02LoraModule::DataEvent::Subscriber DxSmartLr02LoraModule::data_event() { @@ -293,44 +194,37 @@ ActionPtr DxSmartLr02LoraModule::SetPowerSaveParam(LoraPowerSaveParam const& psp) { auto lora_module_operation = ActionPtr{action_context_}; - operation_queue_->Push(Stage([this, lora_module_operation, psp{psp}]() { - auto pipeline = MakeActionPtr( - action_context_, - // Enter AT command mode - Stage([this]() { return EnterAtMode(); }), - // Configure Lora Module Mode - Stage( - [this, psp]() { return SetLoraModuleMode(psp.lora_module_mode); }), - // Configure Lora Module Level - Stage([this, psp]() { - return SetLoraModuleLevel(psp.lora_module_level); - }), - // Configure Lora Module Power - Stage([this, psp]() { - return SetLoraModulePower(psp.lora_module_power); - }), - // Configure Lora Module BandWidth - Stage([this, psp]() { - return SetLoraModuleBandWidth(psp.lora_module_band_width); - }), - // Configure Lora Module Coding Rate - Stage([this, psp]() { - return SetLoraModuleCodingRate(psp.lora_module_coding_rate); - }), - // Configure Lora Module Spreading Factor - Stage([this, psp]() { - return SetLoraModuleSpreadingFactor(psp.lora_module_spreading_factor); - }), - // Exit AT command mode - Stage([this]() { return ExitAtMode(); })); - pipeline->StatusEvent().Subscribe(ActionHandler{ - OnResult{ - [lora_module_operation]() { lora_module_operation->Notify(); }}, - OnError{[lora_module_operation]() { lora_module_operation->Failed(); }}, - OnStop{[lora_module_operation]() { lora_module_operation->Stop(); }}}); + auto pipeline = MakeActionPtr( + action_context_, + // Enter AT command mode + Stage([this]() { return EnterAtMode(); }), + // Configure Lora Module Mode + Stage([this, psp]() { return SetLoraModuleMode(psp.lora_module_mode); }), + // Configure Lora Module Level + Stage( + [this, psp]() { return SetLoraModuleLevel(psp.lora_module_level); }), + // Configure Lora Module Power + Stage( + [this, psp]() { return SetLoraModulePower(psp.lora_module_power); }), + // Configure Lora Module BandWidth + Stage([this, psp]() { + return SetLoraModuleBandWidth(psp.lora_module_band_width); + }), + // Configure Lora Module Coding Rate + Stage([this, psp]() { + return SetLoraModuleCodingRate(psp.lora_module_coding_rate); + }), + // Configure Lora Module Spreading Factor + Stage([this, psp]() { + return SetLoraModuleSpreadingFactor(psp.lora_module_spreading_factor); + }), + // Exit AT command mode + Stage([this]() { return ExitAtMode(); })); - return pipeline; - })); + pipeline->StatusEvent().Subscribe(ActionHandler{ + OnResult{[lora_module_operation]() { lora_module_operation->Notify(); }}, + OnError{[lora_module_operation]() { lora_module_operation->Failed(); }}, + OnStop{[lora_module_operation]() { lora_module_operation->Stop(); }}}); return lora_module_operation; } @@ -340,29 +234,26 @@ DxSmartLr02LoraModule::PowerOff() { return {}; } +std::uint16_t DxSmartLr02LoraModule::GetMtu() { return kLoraModuleMTU; } + ActionPtr DxSmartLr02LoraModule::SetLoraModuleAddress(std::uint16_t const& address) { auto lora_module_operation = ActionPtr{action_context_}; - operation_queue_->Push(Stage([this, lora_module_operation, address]() { - auto pipeline = MakeActionPtr( - action_context_, - // Enter AT command mode - Stage([this]() { return EnterAtMode(); }), Stage([this, address]() { - return at_comm_support_.MakeRequest( - "AT+MAC" + AdressToString(address), kWaitOk); - }), - // Exit AT command mode - Stage([this]() { return ExitAtMode(); })); - - pipeline->StatusEvent().Subscribe(ActionHandler{ - OnResult{ - [lora_module_operation]() { lora_module_operation->Notify(); }}, - OnError{[lora_module_operation]() { lora_module_operation->Failed(); }}, - OnStop{[lora_module_operation]() { lora_module_operation->Stop(); }}}); + auto pipeline = MakeActionPtr( + action_context_, + // Enter AT command mode + Stage([this]() { return EnterAtMode(); }), Stage([this, address]() { + return at_support_.MakeRequest("AT+MAC" + AdressToString(address), + kWaitOk); + }), + // Exit AT command mode + Stage([this]() { return ExitAtMode(); })); - return pipeline; - })); + pipeline->StatusEvent().Subscribe(ActionHandler{ + OnResult{[lora_module_operation]() { lora_module_operation->Notify(); }}, + OnError{[lora_module_operation]() { lora_module_operation->Failed(); }}, + OnStop{[lora_module_operation]() { lora_module_operation->Stop(); }}}); return lora_module_operation; } @@ -375,25 +266,20 @@ DxSmartLr02LoraModule::SetLoraModuleChannel(std::uint8_t const& channel) { auto lora_module_operation = ActionPtr{action_context_}; - operation_queue_->Push(Stage([this, lora_module_operation, channel]() { - auto pipeline = MakeActionPtr( - action_context_, - // Enter AT command mode - Stage([this]() { return EnterAtMode(); }), Stage([this, channel]() { - return at_comm_support_.MakeRequest( - "AT+CHANNEL" + ChannelToString(channel), kWaitOk); - }), - // Exit AT command mode - Stage([this]() { return ExitAtMode(); })); - - pipeline->StatusEvent().Subscribe(ActionHandler{ - OnResult{ - [lora_module_operation]() { lora_module_operation->Notify(); }}, - OnError{[lora_module_operation]() { lora_module_operation->Failed(); }}, - OnStop{[lora_module_operation]() { lora_module_operation->Stop(); }}}); + auto pipeline = MakeActionPtr( + action_context_, + // Enter AT command mode + Stage([this]() { return EnterAtMode(); }), Stage([this, channel]() { + return at_support_.MakeRequest("AT+CHANNEL" + ChannelToString(channel), + kWaitOk); + }), + // Exit AT command mode + Stage([this]() { return ExitAtMode(); })); - return pipeline; - })); + pipeline->StatusEvent().Subscribe(ActionHandler{ + OnResult{[lora_module_operation]() { lora_module_operation->Notify(); }}, + OnError{[lora_module_operation]() { lora_module_operation->Failed(); }}, + OnStop{[lora_module_operation]() { lora_module_operation->Stop(); }}}); return lora_module_operation; } @@ -403,25 +289,20 @@ DxSmartLr02LoraModule::SetLoraModuleCRCCheck( kLoraModuleCRCCheck const& crc_check) { auto lora_module_operation = ActionPtr{action_context_}; - operation_queue_->Push(Stage([this, lora_module_operation, crc_check]() { - auto pipeline = MakeActionPtr( - action_context_, - // Enter AT command mode - Stage([this]() { return EnterAtMode(); }), Stage([this, crc_check]() { - return at_comm_support_.MakeRequest( - "AT+CRC" + std::to_string(static_cast(crc_check)), kWaitOk); - }), - // Exit AT command mode - Stage([this]() { return ExitAtMode(); })); + auto pipeline = MakeActionPtr( + action_context_, + // Enter AT command mode + Stage([this]() { return EnterAtMode(); }), Stage([this, crc_check]() { + return at_support_.MakeRequest( + "AT+CRC" + std::to_string(static_cast(crc_check)), kWaitOk); + }), + // Exit AT command mode + Stage([this]() { return ExitAtMode(); })); - pipeline->StatusEvent().Subscribe(ActionHandler{ - OnResult{ - [lora_module_operation]() { lora_module_operation->Notify(); }}, - OnError{[lora_module_operation]() { lora_module_operation->Failed(); }}, - OnStop{[lora_module_operation]() { lora_module_operation->Stop(); }}}); - - return pipeline; - })); + pipeline->StatusEvent().Subscribe(ActionHandler{ + OnResult{[lora_module_operation]() { lora_module_operation->Notify(); }}, + OnError{[lora_module_operation]() { lora_module_operation->Failed(); }}, + OnStop{[lora_module_operation]() { lora_module_operation->Stop(); }}}); return lora_module_operation; } @@ -431,28 +312,22 @@ DxSmartLr02LoraModule::SetLoraModuleIQSignalInversion( kLoraModuleIQSignalInversion const& signal_inversion) { auto lora_module_operation = ActionPtr{action_context_}; - operation_queue_->Push(Stage([this, lora_module_operation, - signal_inversion]() { - auto pipeline = MakeActionPtr( - action_context_, - // Enter AT command mode - Stage([this]() { return EnterAtMode(); }), - Stage([this, signal_inversion]() { - return at_comm_support_.MakeRequest( - "AT+IQ" + std::to_string(static_cast(signal_inversion)), - kWaitOk); - }), - // Exit AT command mode - Stage([this]() { return ExitAtMode(); })); - - pipeline->StatusEvent().Subscribe(ActionHandler{ - OnResult{ - [lora_module_operation]() { lora_module_operation->Notify(); }}, - OnError{[lora_module_operation]() { lora_module_operation->Failed(); }}, - OnStop{[lora_module_operation]() { lora_module_operation->Stop(); }}}); + auto pipeline = MakeActionPtr( + action_context_, + // Enter AT command mode + Stage([this]() { return EnterAtMode(); }), + Stage([this, signal_inversion]() { + return at_support_.MakeRequest( + "AT+IQ" + std::to_string(static_cast(signal_inversion)), + kWaitOk); + }), + // Exit AT command mode + Stage([this]() { return ExitAtMode(); })); - return pipeline; - })); + pipeline->StatusEvent().Subscribe(ActionHandler{ + OnResult{[lora_module_operation]() { lora_module_operation->Notify(); }}, + OnError{[lora_module_operation]() { lora_module_operation->Failed(); }}, + OnStop{[lora_module_operation]() { lora_module_operation->Stop(); }}}); return lora_module_operation; } @@ -461,17 +336,11 @@ DxSmartLr02LoraModule::SetLoraModuleIQSignalInversion( void DxSmartLr02LoraModule::Init() { operation_queue_->Push(Stage([this]() { auto init_pipeline = MakeActionPtr( - action_context_, - // Enter AT command mode - Stage([this]() { return EnterAtMode(); }), - Stage([this]() { return at_comm_support_.MakeRequest("AT", kWaitOk); }), - Stage([this]() { + action_context_, Stage([this]() { return SetupSerialPort(lora_module_init_.serial_init); }), Stage([this]() { return SetPowerSaveParam(lora_module_init_.psp); }), Stage([this]() { return SetupLoraNet(lora_module_init_); }), - // Exit AT command mode - Stage([this]() { return ExitAtMode(); }), Stage(action_context_, [this]() { initiated_ = true; return UpdateStatus::Result(); @@ -486,14 +355,14 @@ void DxSmartLr02LoraModule::Init() { })); } -ActionPtr DxSmartLr02LoraModule::OpenTcpConnection( +ActionPtr DxSmartLr02LoraModule::OpenLoraConnection( ActionPtr open_network_operation, std::string const& host, std::uint16_t port) { return MakeActionPtr( action_context_, Stage([this, open_network_operation{std::move(open_network_operation)}, host{host}, port]() { - auto open_operation = ActionPtr{ + auto open_operation = ActionPtr{ action_context_, *this, host, port}; open_operation->StatusEvent().Subscribe(ActionHandler{ @@ -509,89 +378,32 @@ ActionPtr DxSmartLr02LoraModule::OpenTcpConnection( })); } -ActionPtr DxSmartLr02LoraModule::OpenUdpConnection( - ActionPtr open_network_operation, - std::string const& host, std::uint16_t port) { +ActionPtr DxSmartLr02LoraModule::SendData( + ConnectionLoraIndex /* connection */, DataBuffer const& data) { return MakeActionPtr( - action_context_, - Stage([this, open_network_operation{std::move(open_network_operation)}, - host{host}, port]() { - auto open_operation = ActionPtr{ - action_context_, *this, host, port}; - - open_operation->StatusEvent().Subscribe(ActionHandler{ - OnResult{[open_network_operation](auto const& action) { - open_network_operation->SetValue(action.connection_index()); - }}, - OnError{[open_network_operation]() { - open_network_operation->Reject(); - }}, + action_context_, Stage([this, data{data}]() mutable { + return at_support_.MakeRequest([this, data{std::move(data)}]() { + auto write_action = ActionPtr{action_context_}; + serial_->Write(data); + write_action->Notify(); + return write_action; }); - - return open_operation; })); } -void DxSmartLr02LoraModule::SetupPoll() { - poll_listener_ = at_comm_support_.ListenForResponse( - "#XPOLL: ", [this](auto& at_buffer, auto pos) { - std::int32_t handle{}; - std::string flags; - AtSupport::ParseResponse(*pos, "#XPOLL", handle, flags); - PollEvent(handle, flags); - return at_buffer.erase(pos); - }); - - // TODO: config for poll interval - poll_task_ = ActionPtr{ - action_context_, - [this]() { - if (connections_.empty()) { - return; - } - // add poll to operation queue - operation_queue_->Push(Stage([this]() { return Poll(); })); - }, - std::chrono::milliseconds{100}}; -} +void DxSmartLr02LoraModule::ReadPacket(DataBuffer const& data) { + ConnectionLoraIndex connection{}; -ActionPtr DxSmartLr02LoraModule::Poll() { - return MakeActionPtr(action_context_, Stage([this]() { - std::string handles; - for (auto ci : connections_) { - handles += "," + std::to_string(ci); - } - return at_comm_support_.MakeRequest( - "#XPOLL=0" + handles, kWaitOk); - })); -} - -void DxSmartLr02LoraModule::PollEvent(std::int32_t handle, - std::string_view flags) { - auto flags_val = FromChars(flags); - if (!flags_val) { - return; - } - - // get connection index - auto it = connections_.find(static_cast(handle)); - if (it == std::end(connections_)) { - AE_TELED_ERROR("Poll unknown handle {}", handle); - return; - } - - constexpr std::uint32_t kPollIn = 0x01; - if (*flags_val | kPollIn) { - operation_queue_->Push( - Stage([this, connection{*it}]() { return ReadPacket(connection); })); - } + AE_TELED_DEBUG("Received {} bytes.", data.size()); + // Emit the received data + data_event_.Emit(connection, data); } ActionPtr DxSmartLr02LoraModule::EnterAtMode() { if (at_mode_ == false) { at_mode_ = true; return MakeActionPtr(action_context_, Stage([this]() { - return at_comm_support_.MakeRequest( + return at_support_.MakeRequest( "+++", kWaitEntryAt); })); } @@ -603,7 +415,7 @@ ActionPtr DxSmartLr02LoraModule::ExitAtMode() { if (at_mode_ == true) { at_mode_ = false; return MakeActionPtr(action_context_, Stage([this]() { - return at_comm_support_.MakeRequest( + return at_support_.MakeRequest( "+++", kWaitExitAt, kWaitPowerOn); })); } @@ -615,7 +427,7 @@ ActionPtr DxSmartLr02LoraModule::SetLoraModuleMode( kLoraModuleMode const& mode) { return MakeActionPtr( action_context_, Stage([this, mode]() { - return at_comm_support_.MakeRequest( + return at_support_.MakeRequest( "AT+MODE" + std::to_string(static_cast(mode)), kWaitOk); })); } @@ -624,7 +436,7 @@ ActionPtr DxSmartLr02LoraModule::SetLoraModuleLevel( kLoraModuleLevel const& level) { return MakeActionPtr( action_context_, Stage([this, level]() { - return at_comm_support_.MakeRequest( + return at_support_.MakeRequest( "AT+LEVEL" + std::to_string(static_cast(level)), kWaitOk); })); } @@ -633,7 +445,7 @@ ActionPtr DxSmartLr02LoraModule::SetLoraModulePower( kLoraModulePower const& power) { return MakeActionPtr( action_context_, Stage([this, power]() { - return at_comm_support_.MakeRequest( + return at_support_.MakeRequest( "AT+POWE" + std::to_string(static_cast(power)), kWaitOk); })); } @@ -642,7 +454,7 @@ ActionPtr DxSmartLr02LoraModule::SetLoraModuleBandWidth( kLoraModuleBandWidth const& band_width) { return MakeActionPtr( action_context_, Stage([this, band_width]() { - return at_comm_support_.MakeRequest( + return at_support_.MakeRequest( "AT+BW" + std::to_string(static_cast(band_width)), kWaitOk); })); } @@ -651,7 +463,7 @@ ActionPtr DxSmartLr02LoraModule::SetLoraModuleCodingRate( kLoraModuleCodingRate const& coding_rate) { return MakeActionPtr( action_context_, Stage([this, coding_rate]() { - return at_comm_support_.MakeRequest( + return at_support_.MakeRequest( "AT+CR" + std::to_string(static_cast(coding_rate)), kWaitOk); })); } @@ -660,22 +472,25 @@ ActionPtr DxSmartLr02LoraModule::SetLoraModuleSpreadingFactor( kLoraModuleSpreadingFactor const& spreading_factor) { return MakeActionPtr( action_context_, Stage([this, spreading_factor]() { - return at_comm_support_.MakeRequest( + return at_support_.MakeRequest( "AT+SF" + std::to_string(static_cast(spreading_factor)), kWaitOk); })); } ActionPtr DxSmartLr02LoraModule::SetupSerialPort( - SerialInit& serial_init) { + SerialInit const& serial_init) { return MakeActionPtr( - action_context_, Stage([this, serial_init]() { + action_context_, + // Enter AT command mode + Stage([this]() { return EnterAtMode(); }), Stage([this, serial_init]() { return SetBaudRate(serial_init.baud_rate); }), Stage([this, serial_init]() { return SetParity(serial_init.parity); }), - Stage([this, serial_init]() { - return SetStopBits(serial_init.stop_bits); - })); + Stage( + [this, serial_init]() { return SetStopBits(serial_init.stop_bits); }), + // Exit AT command mode + Stage([this]() { return ExitAtMode(); })); } ActionPtr DxSmartLr02LoraModule::SetBaudRate(kBaudRate baud_rate) { @@ -685,8 +500,8 @@ ActionPtr DxSmartLr02LoraModule::SetBaudRate(kBaudRate baud_rate) { } return MakeActionPtr(action_context_, Stage([this, it]() { - return at_comm_support_.MakeRequest( - it->second, kWaitOk); + return at_support_.MakeRequest(it->second, + kWaitOk); })); } @@ -709,8 +524,7 @@ ActionPtr DxSmartLr02LoraModule::SetParity(kParity parity) { } return MakeActionPtr(action_context_, Stage([this, cmd]() { - return at_comm_support_.MakeRequest(cmd, - kWaitOk); + return at_support_.MakeRequest(cmd, kWaitOk); })); } @@ -729,16 +543,14 @@ ActionPtr DxSmartLr02LoraModule::SetStopBits(kStopBits stop_bits) { break; } - return MakeActionPtr(action_context_, + return MakeActionPtr( + action_context_, - Stage([this, cmd]() { - return at_comm_support_.MakeRequest(cmd, - kWaitOk); - })); + Stage([this, cmd]() { return at_support_.MakeRequest(cmd, kWaitOk); })); } ActionPtr DxSmartLr02LoraModule::SetupLoraNet( - LoraModuleInit& lora_module_init) { + LoraModuleInit const& lora_module_init) { return MakeActionPtr( action_context_, Stage([this, lora_module_init]() { return SetLoraModuleAddress(lora_module_init.lora_module_my_adress); diff --git a/aether/lora_modules/dx_smart_lr02_lm.h b/aether/lora_modules/dx_smart_lr02_lm.h index 01ae3aa6..7dcb4a23 100644 --- a/aether/lora_modules/dx_smart_lr02_lm.h +++ b/aether/lora_modules/dx_smart_lr02_lm.h @@ -33,8 +33,7 @@ # include "aether/lora_modules/ilora_module_driver.h" namespace ae { -class DxSmartLr02TcpOpenNetwork; -class DxSmartLr02UdpOpenNetwork; +class DxSmartLr02LoraOpenNetwork; static const std::map baud_rate_commands_lr02 = { {kBaudRate::kBaudRate1200, "AT+BAUD1"}, @@ -48,9 +47,8 @@ static const std::map baud_rate_commands_lr02 = { {kBaudRate::kBaudRate128000, "AT+BAUD9"}}; class DxSmartLr02LoraModule final : public ILoraModuleDriver { - friend class DxSmartLr02TcpOpenNetwork; - friend class DxSmartLr02UdpOpenNetwork; - static constexpr std::uint16_t kLoraModuleMTU{400}; + friend class DxSmartLr02LoraOpenNetwork; + static constexpr std::uint16_t kLoraModuleMTU{200}; public: explicit DxSmartLr02LoraModule(ActionContext action_context, @@ -60,24 +58,18 @@ class DxSmartLr02LoraModule final : public ILoraModuleDriver { ActionPtr Start() override; ActionPtr Stop() override; - ActionPtr OpenNetwork(Protocol protocol, - std::string const& host, - std::uint16_t port) override; - ActionPtr CloseNetwork( - ConnectionLoraIndex connect_index) override; ActionPtr WritePacket(ConnectionLoraIndex connect_index, - ae::DataBuffer const& data) override; - + DataBuffer const& data) override; DataEvent::Subscriber data_event() override; - ActionPtr SetPowerSaveParam( LoraPowerSaveParam const& psp) override; ActionPtr PowerOff() override; + std::uint16_t GetMtu() override; + ActionPtr SetLoraModuleAddress( std::uint16_t const& address); // Module address ActionPtr SetLoraModuleChannel( std::uint8_t const& channel); // Module channel - ActionPtr SetLoraModuleCRCCheck( kLoraModuleCRCCheck const& crc_check); // Module crc check ActionPtr SetLoraModuleIQSignalInversion( @@ -87,27 +79,19 @@ class DxSmartLr02LoraModule final : public ILoraModuleDriver { private: void Init(); - ActionPtr OpenTcpConnection( - ActionPtr open_network_operation, - std::string const& host, std::uint16_t port); - - ActionPtr OpenUdpConnection( + ActionPtr OpenLoraConnection( ActionPtr open_network_operation, std::string const& host, std::uint16_t port); ActionPtr SendData(ConnectionLoraIndex connection, DataBuffer const& data); - ActionPtr ReadPacket(ConnectionLoraIndex connection); - - void SetupPoll(); - ActionPtr Poll(); - void PollEvent(std::int32_t handle, std::string_view flags); + void ReadPacket(DataBuffer const& data); ActionContext action_context_; LoraModuleInit lora_module_init_; std::unique_ptr serial_; std::set connections_; - AtSupport at_comm_support_; + AtSupport at_support_; DataEvent data_event_; ActionPtr poll_task_; std::unique_ptr poll_listener_; @@ -132,12 +116,13 @@ class DxSmartLr02LoraModule final : public ILoraModuleDriver { ActionPtr SetLoraModuleSpreadingFactor( kLoraModuleSpreadingFactor const& spreading_factor); // Module spreading factor - ActionPtr SetupSerialPort(SerialInit& serial_init); + + ActionPtr SetupSerialPort(SerialInit const& serial_init); ActionPtr SetBaudRate(kBaudRate baud_rate); ActionPtr SetParity(kParity parity); ActionPtr SetStopBits(kStopBits stop_bits); - ActionPtr SetupLoraNet(LoraModuleInit& lora_module_init); + ActionPtr SetupLoraNet(LoraModuleInit const& lora_module_init); std::string AdressToString(uint16_t value); std::string ChannelToString(uint8_t value); diff --git a/aether/lora_modules/ebyte_e22_lm.cpp b/aether/lora_modules/ebyte_e22_lm.cpp index c260cdb4..685e26d6 100644 --- a/aether/lora_modules/ebyte_e22_lm.cpp +++ b/aether/lora_modules/ebyte_e22_lm.cpp @@ -32,7 +32,50 @@ namespace ae { static constexpr Duration kOneSecond = std::chrono::milliseconds{1000}; static constexpr Duration kTwoSeconds = std::chrono::milliseconds{2000}; -static constexpr Duration kTenSeconds = std::chrono::milliseconds{10000}; +static const AtRequest::Wait kWaitOk{"OK", kOneSecond}; +static const AtRequest::Wait kWaitOkTwoSeconds{"OK", kTwoSeconds}; +static const AtRequest::Wait kWaitEntryAt{"Entry AT", kOneSecond}; +static const AtRequest::Wait kWaitExitAt{"Exit AT", kOneSecond}; +static const AtRequest::Wait kWaitPowerOn{"Power on", kOneSecond}; + +class EbyteE22LoraOpenNetwork final : public Action { + public: + EbyteE22LoraOpenNetwork(ActionContext action_context, + EbyteE22LoraModule& /* lora_module */, + std::string host, std::uint16_t port) + : Action{action_context}, + action_context_{action_context}, + host_{std::move(host)}, + port_{port} { + AE_TELED_DEBUG("Open lora connection for {}:{}", host_, port_); + } + + UpdateStatus Update() const { + if (success_) { + return UpdateStatus::Result(); + } + if (error_) { + return UpdateStatus::Error(); + } + if (stop_) { + return UpdateStatus::Stop(); + } + return {}; + } + + ConnectionLoraIndex connection_index() const { return connection_index_; } + + private: + ActionContext action_context_; + std::string host_; + std::uint16_t port_; + ActionPtr operation_pipeline_; + Subscription operation_sub_; + ConnectionLoraIndex connection_index_ = kInvalidConnectionLoraIndex; + bool success_{}; + bool error_{}; + bool stop_{}; +}; EbyteE22LoraModule::EbyteE22LoraModule(ActionContext action_context, IPoller::ptr const& poller, @@ -41,10 +84,8 @@ EbyteE22LoraModule::EbyteE22LoraModule(ActionContext action_context, lora_module_init_{std::move(lora_module_init)}, serial_{SerialPortFactory::CreatePort(action_context_, std::move(poller), lora_module_init_.serial_init)}, - at_comm_support_{action_context_, *serial_}, - operation_queue_{action_context_}, - initiated_{false}, - started_{false} { + at_support_{action_context_, *serial_}, + operation_queue_{action_context_} { Init(); Start(); } @@ -59,42 +100,32 @@ ActionPtr EbyteE22LoraModule::Stop() { return {}; } -ActionPtr -EbyteE22LoraModule::OpenNetwork(ae::Protocol /* protocol*/, - std::string const& /*host*/, - std::uint16_t /* port*/) { - return {}; -} +ActionPtr EbyteE22LoraModule::WritePacket( + ae::ConnectionLoraIndex connect_index, ae::DataBuffer const& data) { + if (data.size() > kLoraModuleMTU) { + assert(false); + return {}; + } -ActionPtr -EbyteE22LoraModule::CloseNetwork(ae::ConnectionLoraIndex /*connect_index*/) { - return {}; -} -// void EbyteE22LoraModule::CloseNetwork( -// ae::ConnectionLoraIndex /*connect_index*/){}; + auto write_notify = ActionPtr{action_context_}; -ActionPtr -EbyteE22LoraModule::WritePacket(ae::ConnectionLoraIndex /*connect_index*/, - ae::DataBuffer const& /*data*/) { - return {}; -} -// void EbyteE22LoraModule::WritePacket(ae::ConnectionLoraIndex -// /*connect_index*/, -// ae::DataBuffer const& /*data*/) {}; + AE_TELED_DEBUG("Queue write packet for data size {}", data.size()); -ActionPtr EbyteE22LoraModule::ReadPacket( - ConnectionLoraIndex /* connection */) { - return {}; + operation_queue_->Push( + Stage([this, write_notify, connect_index, data{data}]() { + auto write_pipeline = SendData(connect_index, data); + write_pipeline->StatusEvent().Subscribe(ActionHandler{ + OnResult{[write_notify]() { write_notify->Notify(); }}, + OnError{[write_notify]() { write_notify->Failed(); }}, + OnStop{[write_notify]() { write_notify->Stop(); }}, + }); + return write_pipeline; + })); + + return write_notify; } -// DataBuffer EbyteE22LoraModule::ReadPacket( -// ae::ConnectionLoraIndex /*connect_index*/, ae::Duration /*timeout*/) { -// DataBuffer data{}; -// -// return data; -// }; -EbyteE22LoraModule::DataEvent::Subscriber -EbyteE22LoraModule::data_event() { +EbyteE22LoraModule::DataEvent::Subscriber EbyteE22LoraModule::data_event() { return EventSubscriber{data_event_}; } @@ -108,6 +139,8 @@ EbyteE22LoraModule::PowerOff() { return {}; } +std::uint16_t EbyteE22LoraModule::GetMtu() { return kLoraModuleMTU; } + ActionPtr EbyteE22LoraModule::SetLoraModuleAddress(std::uint16_t const& /*address*/) { return {}; @@ -119,51 +152,198 @@ EbyteE22LoraModule::SetLoraModuleChannel(std::uint8_t const& /*channel*/) { } ActionPtr -EbyteE22LoraModule::SetLoraModuleMode(kLoraModuleMode const& /*mode*/) { +EbyteE22LoraModule::SetLoraModuleCRCCheck( + kLoraModuleCRCCheck const& /*crc_check*/) { return {}; } ActionPtr -EbyteE22LoraModule::SetLoraModuleLevel(kLoraModuleLevel const& /*level*/) { +EbyteE22LoraModule::SetLoraModuleIQSignalInversion( + kLoraModuleIQSignalInversion const& /*signal_inversion*/) { return {}; } -ActionPtr -EbyteE22LoraModule::SetLoraModulePower(kLoraModulePower const& /*power*/) { +// ============================private members=============================== // +void EbyteE22LoraModule::Init() {} + +ActionPtr EbyteE22LoraModule::OpenLoraConnection( + ActionPtr /* open_network_operation */, + std::string const& /* host */, std::uint16_t /* port */) { return {}; } -ActionPtr -EbyteE22LoraModule::SetLoraModuleBandWidth( - kLoraModuleBandWidth const& /*band_width*/) { +ActionPtr EbyteE22LoraModule::SendData( + ConnectionLoraIndex /* connection */, DataBuffer const& /* data */) { return {}; } -ActionPtr -EbyteE22LoraModule::SetLoraModuleCodingRate( - kLoraModuleCodingRate const& /*coding_rate*/) { - return {}; +void EbyteE22LoraModule::ReadPacket( + DataBuffer const& /* data */) { } -ActionPtr -EbyteE22LoraModule::SetLoraModuleSpreadingFactor( - kLoraModuleSpreadingFactor const& /*spreading_factor*/) { - return {}; +ActionPtr EbyteE22LoraModule::EnterAtMode() { return {}; } + +ActionPtr EbyteE22LoraModule::ExitAtMode() { return {}; } + +ActionPtr EbyteE22LoraModule::SetLoraModuleMode( + kLoraModuleMode const& mode) { + return MakeActionPtr( + action_context_, Stage([this, mode]() { + return at_support_.MakeRequest( + "AT+MODE" + std::to_string(static_cast(mode)), kWaitOk); + })); } -ActionPtr -EbyteE22LoraModule::SetLoraModuleCRCCheck( - kLoraModuleCRCCheck const& /*crc_check*/) { - return {}; +ActionPtr EbyteE22LoraModule::SetLoraModuleLevel( + kLoraModuleLevel const& level) { + return MakeActionPtr( + action_context_, Stage([this, level]() { + return at_support_.MakeRequest( + "AT+LEVEL" + std::to_string(static_cast(level)), kWaitOk); + })); } -ActionPtr -EbyteE22LoraModule::SetLoraModuleIQSignalInversion( - kLoraModuleIQSignalInversion const& /*signal_inversion*/) { - return {}; +ActionPtr EbyteE22LoraModule::SetLoraModulePower( + kLoraModulePower const& power) { + return MakeActionPtr( + action_context_, Stage([this, power]() { + return at_support_.MakeRequest( + "AT+POWE" + std::to_string(static_cast(power)), kWaitOk); + })); } -void EbyteE22LoraModule::Init() {} +ActionPtr EbyteE22LoraModule::SetLoraModuleBandWidth( + kLoraModuleBandWidth const& band_width) { + return MakeActionPtr( + action_context_, Stage([this, band_width]() { + return at_support_.MakeRequest( + "AT+BW" + std::to_string(static_cast(band_width)), kWaitOk); + })); +} + +ActionPtr EbyteE22LoraModule::SetLoraModuleCodingRate( + kLoraModuleCodingRate const& coding_rate) { + return MakeActionPtr( + action_context_, Stage([this, coding_rate]() { + return at_support_.MakeRequest( + "AT+CR" + std::to_string(static_cast(coding_rate)), kWaitOk); + })); +} + +ActionPtr EbyteE22LoraModule::SetLoraModuleSpreadingFactor( + kLoraModuleSpreadingFactor const& spreading_factor) { + return MakeActionPtr( + action_context_, Stage([this, spreading_factor]() { + return at_support_.MakeRequest( + "AT+SF" + std::to_string(static_cast(spreading_factor)), + kWaitOk); + })); +} + +ActionPtr EbyteE22LoraModule::SetupSerialPort( + SerialInit& serial_init) { + return MakeActionPtr( + action_context_, Stage([this, serial_init]() { + return SetBaudRate(serial_init.baud_rate); + }), + Stage([this, serial_init]() { return SetParity(serial_init.parity); }), + Stage([this, serial_init]() { + return SetStopBits(serial_init.stop_bits); + })); +} + +ActionPtr EbyteE22LoraModule::SetBaudRate(kBaudRate baud_rate) { + auto it = baud_rate_commands_e22.find(baud_rate); + if (it == baud_rate_commands_e22.end()) { + return {}; + } + + return MakeActionPtr(action_context_, Stage([this, it]() { + return at_support_.MakeRequest(it->second, + kWaitOk); + })); +} + +ActionPtr EbyteE22LoraModule::SetParity(kParity parity) { + std::string cmd{}; + + switch (parity) { + case kParity::kNoParity: + cmd = "AT+PARI0"; // Set no parity + break; + case kParity::kOddParity: + cmd = "AT+PARI1"; // Set odd parity + break; + case kParity::kEvenParity: + cmd = "AT+PARI2"; // Set even parity + break; + default: + return {}; + break; + } + return MakeActionPtr(action_context_, Stage([this, cmd]() { + return at_support_.MakeRequest(cmd, kWaitOk); + })); +} + +ActionPtr EbyteE22LoraModule::SetStopBits(kStopBits stop_bits) { + std::string cmd{}; + + switch (stop_bits) { + case kStopBits::kOneStopBit: + cmd = "AT+STOP1"; // 0 stop bits + break; + case kStopBits::kTwoStopBit: + cmd = "AT+STOP2"; // 2 stop bits + break; + default: + return {}; + break; + } + + return MakeActionPtr( + action_context_, + + Stage([this, cmd]() { return at_support_.MakeRequest(cmd, kWaitOk); })); +} + +ActionPtr EbyteE22LoraModule::SetupLoraNet( + LoraModuleInit& lora_module_init) { + return MakeActionPtr( + action_context_, Stage([this, lora_module_init]() { + return SetLoraModuleAddress(lora_module_init.lora_module_my_adress); + }), + Stage([this, lora_module_init]() { + return SetLoraModuleChannel(lora_module_init.lora_module_channel); + }), + Stage([this, lora_module_init]() { + return SetLoraModuleCRCCheck(lora_module_init.lora_module_crc_check); + }), + Stage([this, lora_module_init]() { + return SetLoraModuleIQSignalInversion( + lora_module_init.lora_module_signal_inversion); + })); +} + +std::string EbyteE22LoraModule::AdressToString(uint16_t value) { + uint8_t high = static_cast((value >> 8)); // High byte + uint8_t low = static_cast(value & 0xFF); // Low byte + char buffer[7]; // Buffer for string + + // Formatting hex string + std::snprintf(buffer, sizeof(buffer), "%02x,%02x", high, low); + + return std::string(buffer); +} + +std::string EbyteE22LoraModule::ChannelToString(uint8_t value) { + char buffer[5]; // Buffer for string + + // Formatting hex string + std::snprintf(buffer, sizeof(buffer), "%02x", value); + + return std::string(buffer); +} } // namespace ae #endif diff --git a/aether/lora_modules/ebyte_e22_lm.h b/aether/lora_modules/ebyte_e22_lm.h index 2bcad4fc..94eacf8a 100644 --- a/aether/lora_modules/ebyte_e22_lm.h +++ b/aether/lora_modules/ebyte_e22_lm.h @@ -34,8 +34,21 @@ # include "aether/lora_modules/ilora_module_driver.h" namespace ae { +class EbyteE22LoraOpenNetwork; + +static const std::map baud_rate_commands_e22 = { + {kBaudRate::kBaudRate1200, "AT+BAUD1"}, + {kBaudRate::kBaudRate2400, "AT+BAUD2"}, + {kBaudRate::kBaudRate4800, "AT+BAUD3"}, + {kBaudRate::kBaudRate9600, "AT+BAUD4"}, + {kBaudRate::kBaudRate19200, "AT+BAUD5"}, + {kBaudRate::kBaudRate38400, "AT+BAUD6"}, + {kBaudRate::kBaudRate57600, "AT+BAUD7"}, + {kBaudRate::kBaudRate115200, "AT+BAUD8"}, + {kBaudRate::kBaudRate128000, "AT+BAUD9"}}; class EbyteE22LoraModule final : public ILoraModuleDriver { + friend class EbyteE22LoraOpenNetwork; static constexpr std::uint16_t kLoraModuleMTU{400}; public: @@ -46,37 +59,18 @@ class EbyteE22LoraModule final : public ILoraModuleDriver { ActionPtr Start() override; ActionPtr Stop() override; - ActionPtr OpenNetwork(ae::Protocol protocol, - std::string const& host, - std::uint16_t port) override; - ActionPtr CloseNetwork( - ae::ConnectionLoraIndex connect_index) override; - ActionPtr WritePacket( - ae::ConnectionLoraIndex connect_index, - ae::DataBuffer const& data) override; - + ActionPtr WritePacket(ConnectionLoraIndex connect_index, + DataBuffer const& data) override; DataEvent::Subscriber data_event() override; - ActionPtr SetPowerSaveParam( LoraPowerSaveParam const& psp) override; ActionPtr PowerOff() override; + std::uint16_t GetMtu() override; + ActionPtr SetLoraModuleAddress( std::uint16_t const& address); // Module address ActionPtr SetLoraModuleChannel( std::uint8_t const& channel); // Module channel - ActionPtr SetLoraModuleMode( - kLoraModuleMode const& mode); // Module mode - ActionPtr SetLoraModuleLevel( - kLoraModuleLevel const& level); // Module level - ActionPtr SetLoraModulePower( - kLoraModulePower const& power); // Module power - ActionPtr SetLoraModuleBandWidth( - kLoraModuleBandWidth const& band_width); // Module BandWidth - ActionPtr SetLoraModuleCodingRate( - kLoraModuleCodingRate const& coding_rate); // Module CodingRate - ActionPtr SetLoraModuleSpreadingFactor( - kLoraModuleSpreadingFactor const& - spreading_factor); // Module spreading factor ActionPtr SetLoraModuleCRCCheck( kLoraModuleCRCCheck const& crc_check); // Module crc check ActionPtr SetLoraModuleIQSignalInversion( @@ -86,26 +80,53 @@ class EbyteE22LoraModule final : public ILoraModuleDriver { private: void Init(); + ActionPtr OpenLoraConnection( + ActionPtr open_network_operation, + std::string const& host, std::uint16_t port); + ActionPtr SendData(ConnectionLoraIndex connection, DataBuffer const& data); - ActionPtr ReadPacket(ConnectionLoraIndex connection); - - void SetupPoll(); - ActionPtr Poll(); - void PollEvent(std::int32_t handle, std::string_view flags); + void ReadPacket(DataBuffer const& data); ActionContext action_context_; LoraModuleInit lora_module_init_; std::unique_ptr serial_; - std::vector connect_vec_; - AtSupport at_comm_support_; + std::set connections_; + AtSupport at_support_; DataEvent data_event_; ActionPtr poll_task_; std::unique_ptr poll_listener_; OwnActionPtr operation_queue_; - bool initiated_; - bool started_; - bool at_mode_{false}; + // bool initiated_{false}; + // bool started_{false}; + // bool at_mode_{false}; + + ActionPtr EnterAtMode(); + ActionPtr ExitAtMode(); + + ActionPtr SetLoraModuleMode( + kLoraModuleMode const& mode); // Module mode + ActionPtr SetLoraModuleLevel( + kLoraModuleLevel const& level); // Module level + ActionPtr SetLoraModulePower( + kLoraModulePower const& power); // Module power + ActionPtr SetLoraModuleBandWidth( + kLoraModuleBandWidth const& band_width); // Module BandWidth + ActionPtr SetLoraModuleCodingRate( + kLoraModuleCodingRate const& coding_rate); // Module CodingRate + ActionPtr SetLoraModuleSpreadingFactor( + kLoraModuleSpreadingFactor const& + spreading_factor); // Module spreading factor + + ActionPtr SetupSerialPort(SerialInit& serial_init); + ActionPtr SetBaudRate(kBaudRate baud_rate); + ActionPtr SetParity(kParity parity); + ActionPtr SetStopBits(kStopBits stop_bits); + + ActionPtr SetupLoraNet(LoraModuleInit& lora_module_init); + + std::string AdressToString(uint16_t value); + std::string ChannelToString(uint8_t value); }; } /* namespace ae */ diff --git a/aether/lora_modules/gw_lora_device.cpp b/aether/lora_modules/gw_lora_device.cpp new file mode 100644 index 00000000..ee077fe6 --- /dev/null +++ b/aether/lora_modules/gw_lora_device.cpp @@ -0,0 +1,77 @@ +/* + * Copyright 2025 Aethernet Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "aether/lora_modules/gw_lora_device.h" + +#if AE_SUPPORT_GATEWAY + +#include "aether/stream_api/stream_write_action.h" +#include "aether/crc.h" +#include "aether/tele/tele.h" + +namespace ae { +namespace gw_lora_device_internal { +class GwStreamWriteAction final : public StreamWriteAction { + public: + explicit GwStreamWriteAction(ActionContext action_context) + : StreamWriteAction{action_context} { + state_ = State::kDone; + } +}; +} // namespace gw_lora_device_internal + +GwLoraDevice::GwLoraDevice(ActionContext action_context) + : action_context_{action_context}, + device_id_{}, + gateway_api_{protocol_context_}, + gateway_client_api_{protocol_context_} {} + +GwLoraDevice::~GwLoraDevice() {} + +ActionPtr GwLoraDevice::ToServer(ClientId client_id, + ServerId server_id, + DataBuffer&& data) { + auto api = ApiContext{gateway_api_}; + api->to_server_id(client_id, server_id, std::move(data)); + DataBuffer packet = std::move(api); + + AE_TELED_DEBUG("Publish from device_id {} data {}", + static_cast(device_id_), packet); + + return ActionPtr{ + action_context_}; +} + +ActionPtr GwLoraDevice::ToServer( + ClientId client_id, ServerEndpoints const& server_endpoints, + DataBuffer&& data) { + auto api = ApiContext{gateway_api_}; + api->to_server(client_id, server_endpoints, std::move(data)); + DataBuffer packet = std::move(api); + + AE_TELED_DEBUG("Publish from device_id {} data {}", + static_cast(device_id_), packet); + + return ActionPtr{ + action_context_}; +} + +GwLoraDevice::FromServerEvent::Subscriber GwLoraDevice::from_server_event() { + return gateway_client_api_.from_server_event(); +} +} // namespace ae + +#endif diff --git a/aether/lora_modules/gw_lora_device.h b/aether/lora_modules/gw_lora_device.h new file mode 100644 index 00000000..16da069f --- /dev/null +++ b/aether/lora_modules/gw_lora_device.h @@ -0,0 +1,71 @@ +/* + * Copyright 2025 Aethernet Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef AETHER_LORA_MODULES_GW_LORA_DEVICE_H_ +#define AETHER_LORA_MODULES_GW_LORA_DEVICE_H_ + +#include "aether/config.h" + +#if AE_SUPPORT_GATEWAY + +#include + +#include "aether/types/server_id.h" +#include "aether/types/client_id.h" +#include "aether/reflect/reflect.h" +#include "aether/gateway_api/gateway_api.h" +#include "aether/transport/gateway/gateway_device.h" + + +namespace ae { +using DeviceId = std::uint8_t; + +static constexpr std::uint16_t kLoraModuleAddress = 2; + +struct LoraPacket { + AE_REFLECT_MEMBERS(address, length, data, crc) + std::uint16_t address{kLoraModuleAddress}; + std::size_t length{0}; + DataBuffer data; + std::uint32_t crc{0}; +}; + +class GwLoraDevice final : public IGatewayDevice { + public: + explicit GwLoraDevice(ActionContext action_context); + ~GwLoraDevice() override; + + ActionPtr ToServer(ClientId client_id, ServerId server_id, + DataBuffer&& data) override; + + ActionPtr ToServer(ClientId client_id, + ServerEndpoints const& server_endpoints, + DataBuffer&& data) override; + + FromServerEvent::Subscriber from_server_event() override; + + private: + ActionContext action_context_; + DeviceId device_id_; + + ProtocolContext protocol_context_; + GatewayApi gateway_api_; + GatewayClientApi gateway_client_api_; +}; +} // namespace ae + +#endif +#endif // AETHER_LORA_MODULES_GW_LORA_DEVICE_H_ diff --git a/aether/lora_modules/ilora_module_driver.h b/aether/lora_modules/ilora_module_driver.h index dccff6e4..91b7306a 100644 --- a/aether/lora_modules/ilora_module_driver.h +++ b/aether/lora_modules/ilora_module_driver.h @@ -45,11 +45,6 @@ class ILoraModuleDriver { virtual ActionPtr Start() = 0; virtual ActionPtr Stop() = 0; - virtual ActionPtr OpenNetwork(Protocol protocol, - std::string const& host, - std::uint16_t port) = 0; - virtual ActionPtr CloseNetwork( - ConnectionLoraIndex connect_index) = 0; virtual ActionPtr WritePacket( ConnectionLoraIndex connect_index, DataBuffer const& data) = 0; virtual DataEvent::Subscriber data_event() = 0; @@ -57,6 +52,8 @@ class ILoraModuleDriver { virtual ActionPtr SetPowerSaveParam( LoraPowerSaveParam const& psp) = 0; virtual ActionPtr PowerOff() = 0; + + virtual std::uint16_t GetMtu() = 0; }; } /* namespace ae */ diff --git a/aether/serial_ports/at_support/at_request.h b/aether/serial_ports/at_support/at_request.h index 26aca89b..f9dea097 100644 --- a/aether/serial_ports/at_support/at_request.h +++ b/aether/serial_ports/at_support/at_request.h @@ -47,7 +47,8 @@ class AtRequest final : public Action { kError, }; - using CommandMaker = SmallFunction()>; + // using CommandMaker = SmallFunction()>; + using CommandMaker = std::function()>; struct Command { std::variant command; diff --git a/aether/types/address.h b/aether/types/address.h index 283ecbf7..2eaca3d2 100644 --- a/aether/types/address.h +++ b/aether/types/address.h @@ -91,6 +91,7 @@ enum class Protocol : std::uint8_t { kTcp, kUdp, kWebSocket, // does not supported really + kLora // TODO: rest does not supported yet /* kAny, diff --git a/examples/cloud/aether_construct_lora_module.h b/examples/cloud/aether_construct_lora_module.h index bf6a68a7..39583b73 100644 --- a/examples/cloud/aether_construct_lora_module.h +++ b/examples/cloud/aether_construct_lora_module.h @@ -22,13 +22,13 @@ #include "aether/config.h" #if CLOUD_TEST_LORA_MODULE -# if !AE_SUPPORT_LORA +# if !AE_SUPPORT_LORA || !AE_SUPPORT_GATEWAY # error "Lora module is not supported" # else namespace ae::cloud_test { static constexpr std::string_view kSerialPortLoraModule = - "COM2"; // Lora module serial port + "COM3"; // Lora module serial port SerialInit serial_init_lora_module = {std::string(kSerialPortLoraModule), kBaudRate::kBaudRate9600}; @@ -44,7 +44,7 @@ LoraPowerSaveParam psp{ ae::LoraModuleInit const lora_module_init{ serial_init_lora_module, // Serial port psp, // Power Save Parameters - kLoraModuleFreqRange::kFREUndef // Frequency range + kLoraModuleFreqRange::kFREUndef, // Frequency range 0, // Lora module address 0, // Lora module BS address 0, // Channel