BLE mbed Endpoint network stack for mbedConnectorInterface. The stack makes use of a special BLE Socket abstraction to create socket() semantics over BLE.
Dependencies: libnsdl_m0 BLE_API Base64 nRF51822 SplitterAssembler
UartRPC.cpp
00001 /** 00002 * @file UartRPC.cpp 00003 * @brief BLE UART RPC implementation 00004 * @author Doug Anson 00005 * @version 1.0 00006 * @see 00007 * 00008 * Copyright (c) 2014 00009 * 00010 * Licensed under the Apache License, Version 2.0 (the "License"); 00011 * you may not use this file except in compliance with the License. 00012 * You may obtain a copy of the License at 00013 * 00014 * http://www.apache.org/licenses/LICENSE-2.0 00015 * 00016 * Unless required by applicable law or agreed to in writing, software 00017 * distributed under the License is distributed on an "AS IS" BASIS, 00018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00019 * See the License for the specific language governing permissions and 00020 * limitations under the License. 00021 */ 00022 00023 #include "UartRPC.h" 00024 #include "UartRPCFunctions.h" 00025 #include "Base64.h" 00026 00027 #ifdef DBG 00028 #undef DBG 00029 #endif 00030 #define DBG std::printf 00031 00032 // immediate response variable pointers... 00033 uint8_t *_immediate_response_buffer = NULL; 00034 int _immediate_response_buffer_length = 0; 00035 00036 // constructor 00037 UartRPC::UartRPC(BLEDevice &ble) : m_dispatcher(ble), m_recv_accumulator() { 00038 this->m_recv_raw_data = NULL; 00039 this->m_recv_raw_data_length = 0; 00040 this->m_local_dispatch_available = false; 00041 this->m_location = NULL; 00042 } 00043 00044 uint8_t __tmp_buffer[MAX_ARGUMENT_LENGTH+1]; 00045 uint8_t base64_buffer[MAX_RESULT_LENGTH+1]; 00046 00047 // dispatch RPC 00048 int UartRPC::dispatch(uint8_t fn_id,void *cb,uint8_t *response,int response_length,const char *format,...) 00049 { 00050 // save off the CB if it exists 00051 this->m_cb = cb; 00052 00053 // serialize the variable arguments into a long string... 00054 va_list args; 00055 memset(__tmp_buffer,0,MAX_ARGUMENT_LENGTH+1); 00056 va_start(args, format); 00057 vsnprintf((char *)__tmp_buffer,MAX_ARGUMENT_LENGTH,format,args); 00058 va_end(args); 00059 00060 // dispatch now... 00061 return this->m_dispatcher.dispatch(fn_id,__tmp_buffer,strlen((char *)__tmp_buffer),response,response_length); 00062 } 00063 00064 // set the location instance 00065 void UartRPC::setLocationInstance(BLELocation *location) { 00066 this->m_location = location; 00067 } 00068 00069 // dispatch locally 00070 void UartRPC::dispatch() { 00071 // assemble the argument buffer... 00072 memset(__tmp_buffer,0,MAX_ARGUMENT_LENGTH+1); 00073 int length = this->m_recv_accumulator.assemble(__tmp_buffer,MAX_ARGUMENT_LENGTH); 00074 00075 // DEBUG 00076 //DBG("UartRPC: dispatch(local): buffer [%s] length=%d\r\n",__tmp_buffer,length); 00077 00078 // parse the buffer 00079 memset(base64_buffer,0,MAX_RESULT_LENGTH+1); 00080 int fn_id = 0; 00081 00082 // strip off head,tail and separator, replace with spaces 00083 int final_length = 0; 00084 for(int i=0;i<length && final_length == 0;++i) { 00085 if (__tmp_buffer[i] == '[') __tmp_buffer[i] = ' '; 00086 if (__tmp_buffer[i] == '|') __tmp_buffer[i] = ' '; 00087 if (__tmp_buffer[i] == ']') { __tmp_buffer[i] = '\0'; final_length = i; } 00088 } 00089 00090 // scan over the two values 00091 sscanf((char *)__tmp_buffer,"%d %s",&fn_id,base64_buffer); 00092 int base64_buffer_length = strlen((char *)base64_buffer); 00093 00094 // DEBUG 00095 //DBG("UartRPC: dispatch(local): fn_id = 0x%.2x base64_buffer = [%s] length=%d\r\n",fn_id,base64_buffer,base64_buffer_length); 00096 00097 // invoke the appropriate function 00098 //DBG("UartRPC: dispatch(local): requested function ID: 0x%.2x...\r\n",fn_id); 00099 switch(fn_id) { 00100 case SOCKET_OPEN_FN: { 00101 // socket open has been attempted... call the CB if it exists and process the status 00102 //DBG("UartRPC: dispatch(local): SOCKET_OPEN_FN length=%d\r\n",base64_buffer_length); 00103 if (this->m_cb != NULL) { 00104 // cast the callback 00105 ble_dispatch_callback_fn cb = (ble_dispatch_callback_fn)this->m_cb; 00106 00107 // parse the packet received for the status 00108 bool open_ok = false; 00109 //DBG("UartRPC: dispatch(local): SOCKET_OPEN_FN socket open status: [%s]\r\n",base64_buffer); 00110 int int_open_ok = 0; 00111 sscanf((char *)base64_buffer,"%d",&int_open_ok); 00112 if (int_open_ok == 1) open_ok = true; 00113 00114 // invoke the callback with the status 00115 //DBG("UartRPC: dispatch(local): SOCKET_OPEN_FN: invoking socket open callback (status: %d)...\r\n",int_open_ok); 00116 cb(open_ok); 00117 //DBG("UartRPC: dispatch(local): SOCKET_OPEN_FN: callback for socket open (status: %d) completed...\r\n",int_open_ok); 00118 } 00119 else { 00120 // no callback given... so we are stuck... 00121 DBG("UartRPC: dispatch(local): SOCKET_OPEN_FN : ERROR no connect() callback function registered!\r\n"); 00122 } 00123 00124 // done with the callback 00125 this->m_cb = NULL; 00126 break; 00127 } 00128 case GET_LOCATION_FN: { 00129 // reset our local dispatch 00130 this->resetLocalDispatch(); 00131 00132 // process the location update response... 00133 Base64 b64; 00134 base64_buffer_length = final_length; 00135 char *location = b64.Decode((char *)base64_buffer,strlen((char *)base64_buffer),(std::size_t *)&base64_buffer_length); 00136 int location_length = base64_buffer_length; // modified by Decode().... 00137 //DBG("UartRPC: dispatch(local): GET_LOCATION_FN: location(%d): %s\r\n",location_length,location); 00138 if (this->m_location != NULL) this->m_location->processLocationUpdateResponse(location,location_length); 00139 00140 // local dispatch is now ready... 00141 this->m_local_dispatch_available = true; 00142 break; 00143 } 00144 case RECV_DATA_FN: { 00145 // reset our local dispatch 00146 //DBG("UartRPC: dispatch(local): resetting...\r\n"); 00147 this->resetLocalDispatch(); 00148 00149 // decode the arguments and save off the local dispatch... 00150 //DBG("UartRPC: dispatch(local): base64 decoding...\r\n"); 00151 Base64 b64; 00152 base64_buffer_length = final_length; 00153 this->m_recv_raw_data = b64.Decode((char *)base64_buffer,strlen((char *)base64_buffer),(std::size_t *)&base64_buffer_length); 00154 this->m_recv_raw_data_length = base64_buffer_length; // modified by Decode().... 00155 00156 // only RECV_DATA_FN is local... make it ready for retrieval and flag it as ready... 00157 //DBG("UartRPC: dispatch(local): RECV_DATA_FN length=%d\r\n",this->m_recv_raw_data_length); 00158 00159 // local dispatch is now ready... 00160 this->m_local_dispatch_available = true; 00161 break; 00162 } 00163 default: { 00164 // all other function ID's are non-local 00165 DBG("UartRPC: dispatch(local): ignoring non-local function call request (id=0x%.2x)...\r\n",fn_id); 00166 00167 // reset the local dispatch 00168 this->resetLocalDispatch(); 00169 break; 00170 } 00171 } 00172 } 00173 00174 // is a local dispatch (packet) available? 00175 bool UartRPC::localDispatchAvailable() { return this->m_local_dispatch_available; }; 00176 00177 // reset the local dispatch availability 00178 void UartRPC::resetLocalDispatch() { 00179 if (this->m_recv_raw_data != NULL) free(this->m_recv_raw_data); 00180 this->m_recv_raw_data = NULL; 00181 this->m_recv_raw_data_length = 0; 00182 this->m_local_dispatch_available = false; 00183 } 00184 00185 // transfer the local dispatch and reset 00186 int UartRPC::retrieveLocalDispatch(uint8_t *buffer,int buffer_length) { 00187 if (this->m_local_dispatch_available == true) { 00188 // copy over the dispatch 00189 memset(buffer,0,buffer_length); 00190 int length = this->m_recv_raw_data_length; 00191 if (length > buffer_length) { 00192 DBG("UartRPC::retrieveLocalDispatch: WARNING: input buffer is too small (is %d bytes, needs to be %d bytes)...\r\n",buffer_length,length); 00193 length = buffer_length; 00194 } 00195 memcpy(buffer,this->m_recv_raw_data,length); 00196 00197 // now reset 00198 this->resetLocalDispatch(); 00199 00200 // return the length 00201 return length; 00202 } 00203 return 0; 00204 } 00205 00206 // accumulate to dispatch locally... 00207 bool UartRPC::accumulate(uint8_t *buffer,int buffer_length) { 00208 //DBG("UartRPC:: accumulating... [%s] length=%d bytes...\r\n",buffer,buffer_length); 00209 00210 // add to the accumulator 00211 this->m_recv_accumulator.add(buffer,buffer_length); 00212 00213 // determine if we have a completed packet by looking for the "tail" 00214 return this->m_recv_accumulator.hasCollectedCharacter(']'); 00215 }
Generated on Sun Jul 17 2022 05:11:06 by 1.7.2