mirror of
				https://github.com/s00500/ESPUI.git
				synced 2025-10-31 17:33:24 +00:00 
			
		
		
		
	Moved the generation of jsonChunks to control manager
This commit is contained in:
		| @@ -79,7 +79,7 @@ void ESPUIclient::FillInHeader(JsonDocument& document) | ||||
|     document[F("type")] = UI_EXTEND_GUI; | ||||
|     document[F("sliderContinuous")] = ESPUI.sliderContinuous; | ||||
|     document[F("startindex")] = 0; | ||||
|     document[F("totalcontrols")] = ESPUI.controlCount; | ||||
|     document[F("totalcontrols")] = ESPUIcontrolMgr.GetControlCount(); | ||||
|     JsonArray items = AllocateJsonArray(document, F("controls")); | ||||
|     JsonObject titleItem = AllocateJsonObject(items); | ||||
|     titleItem[F("type")] = (int)UI_TITLE; | ||||
| @@ -253,213 +253,6 @@ bool ESPUIclient::onWsEvent(AwsEventType type, void* arg, uint8_t* data, size_t | ||||
|     return Response; | ||||
| } | ||||
|  | ||||
| /* | ||||
| Prepare a chunk of elements as a single JSON string. If the allowed number of elements is greater than the total | ||||
| number this will represent the entire UI. More likely, it will represent a small section of the UI to be sent. The | ||||
| client will acknowledge receipt by requesting the next chunk. | ||||
|  */ | ||||
| uint32_t ESPUIclient::prepareJSONChunk(uint16_t startindex, | ||||
|                                       JsonDocument & rootDoc, | ||||
|                                       bool InUpdateMode, | ||||
|                                       String FragmentRequestString) | ||||
| { | ||||
| #ifdef ESP32 | ||||
|     xSemaphoreTake(ESPUI.ControlsSemaphore, portMAX_DELAY); | ||||
| #endif // def ESP32 | ||||
|  | ||||
|     // Serial.println(String("prepareJSONChunk: Start.          InUpdateMode: ") + String(InUpdateMode)); | ||||
|     // Serial.println(String("prepareJSONChunk: Start.            startindex: ") + String(startindex)); | ||||
|     // Serial.println(String("prepareJSONChunk: Start. FragmentRequestString: '") + FragmentRequestString + "'"); | ||||
|     int elementcount = 0; | ||||
|     uint32_t MaxMarshaledJsonSize = (!InUpdateMode) ? ESPUI.jsonInitialDocumentSize: ESPUI.jsonUpdateDocumentSize; | ||||
|     uint32_t EstimatedUsedMarshaledJsonSize = 0; | ||||
|  | ||||
|     do // once | ||||
|     { | ||||
|         // Follow the list until control points to the startindex'th node | ||||
|         Control* control = ESPUI.controls; | ||||
|         uint32_t currentIndex = 0; | ||||
|         uint32_t DataOffset = 0; | ||||
|         JsonArray items = rootDoc[F("controls")]; | ||||
|         bool SingleControl = false; | ||||
|  | ||||
|         if(!emptyString.equals(FragmentRequestString)) | ||||
|         { | ||||
|             // Serial.println(F("prepareJSONChunk:Fragmentation:Got Header (1)")); | ||||
|             // Serial.println(String("prepareJSONChunk:startindex:                  ") + String(startindex)); | ||||
|             // Serial.println(String("prepareJSONChunk:currentIndex:                ") + String(currentIndex)); | ||||
|             // Serial.println(String("prepareJSONChunk:FragmentRequestString:      '") + FragmentRequestString + "'"); | ||||
|  | ||||
|             // this is actually a fragment or directed update request | ||||
|             // parse the string we got from the UI and try to update that specific  | ||||
|             // control. | ||||
|             AllocateJsonDocument(FragmentRequest, FragmentRequestString.length() * 3); | ||||
| /* | ||||
|             ArduinoJson::detail::sizeofObject(N); | ||||
|             if(0 >= FragmentRequest.capacity()) | ||||
|             { | ||||
|                 Serial.println(F("ERROR:prepareJSONChunk:Fragmentation:Could not allocate memory for a fragmentation request. Skipping Response")); | ||||
|                 break; | ||||
|             } | ||||
| */ | ||||
|             size_t FragmentRequestStartOffset = FragmentRequestString.indexOf("{"); | ||||
|             DeserializationError error = deserializeJson(FragmentRequest, FragmentRequestString.substring(FragmentRequestStartOffset)); | ||||
|             if(DeserializationError::Ok != error) | ||||
|             { | ||||
|                 Serial.println(F("ERROR:prepareJSONChunk:Fragmentation:Could not extract json from the fragment request")); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             if(!FragmentRequest.containsKey(F("id"))) | ||||
|             { | ||||
|                 Serial.println(F("ERROR:prepareJSONChunk:Fragmentation:Request does not contain a control ID")); | ||||
|                 break; | ||||
|             } | ||||
|             uint16_t ControlId = uint16_t(FragmentRequest[F("id")]); | ||||
|  | ||||
|             if(!FragmentRequest.containsKey(F("offset"))) | ||||
|             { | ||||
|                 Serial.println(F("ERROR:prepareJSONChunk:Fragmentation:Request does not contain a starting offset")); | ||||
|                 break; | ||||
|             } | ||||
|             DataOffset = uint16_t(FragmentRequest[F("offset")]); | ||||
|             control = ESPUI.getControlNoLock(ControlId); | ||||
|             if(nullptr == control) | ||||
|             { | ||||
|                 Serial.println(String(F("ERROR:prepareJSONChunk:Fragmentation:Requested control: ")) + String(ControlId) + F(" does not exist")); | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             // Serial.println(F("prepareJSONChunk:Fragmentation:disable the control search operation")); | ||||
|             currentIndex = 1; | ||||
|             startindex = 0; | ||||
|             SingleControl = true; | ||||
|         } | ||||
|  | ||||
|         // find a control to send | ||||
|         while ((startindex > currentIndex) && (nullptr != control)) | ||||
|         { | ||||
|             // only count active controls | ||||
|             if (!control->ToBeDeleted()) | ||||
|             { | ||||
|                 if(InUpdateMode) | ||||
|                 { | ||||
|                     // In update mode we only count the controls that have been updated. | ||||
|                     if(control->NeedsSync(CurrentSyncID)) | ||||
|                     { | ||||
|                         ++currentIndex; | ||||
|                     } | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     // not in update mode. Count all active controls | ||||
|                     ++currentIndex; | ||||
|                 } | ||||
|             } | ||||
|             control = control->next; | ||||
|         } | ||||
|  | ||||
|         // any controls left to be processed? | ||||
|         if(nullptr == control) | ||||
|         { | ||||
|             // Serial.println("prepareJSONChunk: No controls to process"); | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         // keep track of the number of elements we have serialised into this | ||||
|         // message. Overflow is detected and handled later in this loop | ||||
|         // and needs an index to the last item added. | ||||
|         while (nullptr != control) | ||||
|         { | ||||
|             // skip deleted controls or controls that have not been updated | ||||
|             if (control->ToBeDeleted() && !SingleControl) | ||||
|             { | ||||
|                 // Serial.println(String("prepareJSONChunk: Ignoring Deleted control: ") + String(control->id)); | ||||
|                 control = control->next; | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if(InUpdateMode && !SingleControl) | ||||
|             { | ||||
|                 if(control->NeedsSync(CurrentSyncID)) | ||||
|                 { | ||||
|                     // dont skip this control | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     // control has not been updated. Skip it | ||||
|                     control = control->next; | ||||
|                     continue; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Serial.println(String(F("prepareJSONChunk: MaxMarshaledJsonSize: ")) + String(MaxMarshaledJsonSize)); | ||||
|             // Serial.println(String(F("prepareJSONChunk: Cur EstimatedUsedMarshaledJsonSize: ")) + String(EstimatedUsedMarshaledJsonSize)); | ||||
|  | ||||
|             JsonObject item = AllocateJsonObject(items); | ||||
|             elementcount++; | ||||
|             uint32_t RemainingSpace = (MaxMarshaledJsonSize - EstimatedUsedMarshaledJsonSize) - 100; | ||||
|             // Serial.println(String(F("prepareJSONChunk: RemainingSpace: ")) + String(RemainingSpace)); | ||||
|             uint32_t SpaceUsedByMarshaledControl = 0; | ||||
|             bool ControlIsFragmented = control->MarshalControl(item,  | ||||
|                                                                InUpdateMode,  | ||||
|                                                                DataOffset,  | ||||
|                                                                RemainingSpace, | ||||
|                                                                SpaceUsedByMarshaledControl); | ||||
|             // Serial.println(String(F("prepareJSONChunk: SpaceUsedByMarshaledControl: ")) + String(SpaceUsedByMarshaledControl)); | ||||
|             EstimatedUsedMarshaledJsonSize += SpaceUsedByMarshaledControl; | ||||
|             // Serial.println(String(F("prepareJSONChunk: New EstimatedUsedMarshaledJsonSize: ")) + String(EstimatedUsedMarshaledJsonSize)); | ||||
|             // Serial.println(String(F("prepareJSONChunk:                ControlIsFragmented: ")) + String(ControlIsFragmented)); | ||||
|  | ||||
|             // did the control get added to the doc? | ||||
|             if (0 == SpaceUsedByMarshaledControl ||  | ||||
|                 (ESPUI.jsonChunkNumberMax > 0 && (elementcount % ESPUI.jsonChunkNumberMax) == 0)) | ||||
|             { | ||||
|                 // Serial.println( String("prepareJSONChunk: too much data in the message. Remove the last entry")); | ||||
|                 if (1 == elementcount) | ||||
|                 { | ||||
|                     // Serial.println(String(F("prepareJSONChunk: Control ")) + String(control->id) + F(" is too large to be sent to the browser.")); | ||||
|                     // Serial.println(String(F("ERROR: prepareJSONChunk: value: ")) + control->value); | ||||
|                     rootDoc.clear(); | ||||
|                     item = AllocateJsonObject(items); | ||||
|                     control->MarshalErrorMessage(item); | ||||
|                     elementcount = 0; | ||||
|                 } | ||||
|                 else | ||||
|                 { | ||||
|                     // Serial.println(String("prepareJSONChunk: Defering control: ") + String(control->id)); | ||||
|                     // Serial.println(String("prepareJSONChunk: elementcount: ") + String(elementcount)); | ||||
|  | ||||
|                     items.remove(elementcount); | ||||
|                     --elementcount; | ||||
|                 } | ||||
|                 // exit the loop | ||||
|                 control = nullptr; | ||||
|             } | ||||
|             else if ((SingleControl) ||  | ||||
|                      (ControlIsFragmented) || | ||||
|                      (MaxMarshaledJsonSize < (EstimatedUsedMarshaledJsonSize + 100))) | ||||
|             { | ||||
|                 // Serial.println("prepareJSONChunk: Doc is Full, Fragmented Control or Single Control. exit loop"); | ||||
|                 control = nullptr; | ||||
|             } | ||||
|             else | ||||
|             { | ||||
|                 // Serial.println("prepareJSONChunk: Next Control"); | ||||
|                 control = control->next; | ||||
|             } | ||||
|         } // end while (control != nullptr) | ||||
|  | ||||
|     } while (false); | ||||
|  | ||||
| #ifdef ESP32 | ||||
|     xSemaphoreGive(ESPUI.ControlsSemaphore); | ||||
| #endif // def ESP32 | ||||
|  | ||||
|     // Serial.println(String("prepareJSONChunk: END: elementcount: ") + String(elementcount)); | ||||
|     return elementcount; | ||||
| } | ||||
|  | ||||
| /* | ||||
| Convert & Transfer Arduino elements to JSON elements. This function sends a chunk of | ||||
| JSON describing the controls of the UI, starting from the control at index startidx. | ||||
| @@ -492,7 +285,7 @@ bool ESPUIclient::SendControlsToClient(uint16_t startidx, ClientUpdateType_t Tra | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         else if ((startidx >= ESPUI.controlCount) && (emptyString.equals(FragmentRequest))) | ||||
|         else if ((startidx >= ESPUIcontrolMgr.GetControlCount()) && (emptyString.equals(FragmentRequest))) | ||||
|         { | ||||
|             // Serial.println(F("ERROR:ESPUIclient:SendControlsToClient: No more controls to send.")); | ||||
|             Response = true; | ||||
| @@ -514,7 +307,7 @@ bool ESPUIclient::SendControlsToClient(uint16_t startidx, ClientUpdateType_t Tra | ||||
|         // Serial.println(String("ESPUIclient:SendControlsToClient:type: ") + String((uint32_t)document["type"])); | ||||
|  | ||||
|         // Serial.println("ESPUIclient:SendControlsToClient: Build Controls."); | ||||
|         if(prepareJSONChunk(startidx, document, ClientUpdateType_t::UpdateNeeded == TransferMode, FragmentRequest)) | ||||
|         if(ESPUIcontrolMgr.prepareJSONChunk(startidx, document, ClientUpdateType_t::UpdateNeeded == TransferMode, FragmentRequest, CurrentSyncID)) | ||||
|         { | ||||
|             #if defined(DEBUG_ESPUI) | ||||
|                 if (ESPUI.verbosity >= Verbosity::VerboseJSON) | ||||
|   | ||||
| @@ -44,7 +44,6 @@ protected: | ||||
|  | ||||
|     bool        CanSend(); | ||||
|     void        FillInHeader(ArduinoJson::JsonDocument& document); | ||||
|     uint32_t    prepareJSONChunk(uint16_t startindex, JsonDocument& rootDoc, bool InUpdateMode, String value); | ||||
|     bool        SendControlsToClient(uint16_t startidx, ClientUpdateType_t TransferMode, String FragmentRequest); | ||||
|  | ||||
|     bool        SendClientNotification(ClientUpdateType_t value); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Martin
					Martin