RBE1001Lib
WebPage.cpp
Go to the documentation of this file.
1 #include <Arduino.h>
2 #include <WebServer.h>
3 #include <HTTP_Method.h>
4 #include "WebPage.h"
5 #include "static/static.h"
6 
7 #include <ESPAsyncWebServer/ESPAsyncWebServer.h>
8 #include "Motor.h"
9 #include "RBE1001Lib.h"
10 #include <stdio.h>
11 #include <string.h>
12 #include "freertos/FreeRTOS.h"
13 #include "freertos/queue.h"
14 
15 AsyncWebServer server(80);
16 AsyncWebSocket ws("/test");
17 static WebPage *thisPage;
18 static char stringBuffer[200];
19 //static uint8_t buffer[labelbuflen];
20 //const String updtime="Uptime";
21 //const String js(nipplejs_min_js);
22 //const String myHTML(index_html);
23 
24 static bool lockOutSending = false;
25 
27 
28 
29 
30 void onWsEvent(AsyncWebSocket * server, AsyncWebSocketClient * client, AwsEventType type, void * arg, uint8_t *data, size_t len){
31  uint32_t *asInt = (uint32_t *)data;
32  float *asFloat = (float *)data;
33  if(type == WS_EVT_CONNECT){
34  //Serial.println("Websocket client connection received");
35  thisPage->markAllDirty();
36  thisPage->updatePID=true;
37  } else if(type == WS_EVT_DISCONNECT){
38  //Serial.println("Client disconnected");
39 
40  } else if(type == WS_EVT_DATA){
41  thisPage->rxPacketCount++;
42  if (len<3) {
43  //Serial.println("Packet too short!");
44  return;
45  }
46  uint32_t command = asInt[0];
47  /*
48  * Data Format
49  * 4B: Message Type
50  * 0x10 (16) Value Update
51  * 4B: value index
52  * 4B: value data
53  * 0x11 (17) Console Data
54  * 4B: length
55  * *B: data
56  *
57  *
58  * 0x1d (29) Bulk Label Update
59  * 4B: Number of Labels in this update
60  * 4B: Start of string data
61  * [repeated next 12B block for each label]
62  * 4B: Index to update
63  * 4B: String Offset in packet
64  * 4B: String Length
65  *
66  * nB: [all label strings concatenated ]
67  *
68  * 0x1e (30) Bulk Value Update
69  * 4B: Number of Values
70  * [repeat for all values]
71  * 4B: value index n
72  * 4B: value data n
73  *
74  * 0x1f (31) New Value
75  * 4B: value index
76  * *B: value name
77  * 0x20 (32) Joystick Update (size 5*4 20 bytes)
78  * 4B: Position X (float, 0.0-1.0)
79  * 4B: Position Y (float, 0.0-1.0)
80  * 4B: Angle (float, radians)
81  * 4B: Magnitude (float, 0.0-1.0)
82  * 0x30 (48) Slider Update
83  * 4B: Slider Number Uint32
84  * 4B: Slider Value (float, 0.0-1.0)
85  * 0x40 (64) Button Update
86  * 4B: Button Number
87  * 4B: Button State (0.0 or 1.0)
88  * 0x50 (80) Heartbeat
89  * 4B: random int.
90  * 0x60 (96): PID Values Update
91  * 4b: PID Channel
92  * 4b: P (float)
93  * 4b: I (float)
94  * 4b: D (float)
95  *
96  */
97 
98  //Serial.println("Command is: "+String(command)+"\t["+String(packetCount++)+"]");
99  switch(command){
100  case 0x20:
101 
102  thisPage->setJoystickValue(asFloat[1], asFloat[2], asFloat[3], asFloat[4]);
103  break;
104  case 0x30:{
105  //Serial.println("Slider Update");
106  //Serial.println("slider:\t"+String(asFloat[1]));
107  //Serial.println("pos:\t"+String(asFloat[2]));
108  thisPage->setSliderValue(asInt[1],asFloat[2]);
109  }
110  break;
111  case 0x40:
112  //Serial.println("Button Update");
113  break;
114  case 0x50:
115  // heartbeat message.
116  thisPage->setHeartbeatUUID(asInt[1]);
117  break;
118  case 0x60:
119 
120  break;
121 
122  }
123 
124 
125  }
126 }
127 
128 
129 
130 char* String2Chars(String str){
131  str.toCharArray(stringBuffer, 200, 0);
132  return stringBuffer;
133 }
134 
135 
137  thisPage = this;
138  joystick.xpos = 0;
139  joystick.ypos = 0;
140  joystick.angle = 0;
141  joystick.mag = 0;
142  for(int i=0; i<numValues; i++) {
143  values[i].used=false;
144  values[i].value=0;
145  values[i].name=String("");
146  values[i].valueDirty=false;
147  values[i].labelDirty=false;
148  }
149  for(int i=0; i<numSliders; i++) sliders[i]=0;
150 }
151 
153  if(millis()-timeSinceLastSend>10){
154  return !lockOutSending;
155  }
156  return false;
157 }
158 void lock(){
159  while(!isSafeToSend()){
160  //Serial.println("W daTA ");
161  delay(1);
162  }
163  lockOutSending=true;
164 }
165 void unlock(){
166  timeSinceLastSend=millis();
167  //Serial.println("R data UnLock");
168  lockOutSending=false;
169 
170 }
171 
172 void updateTask(void *param){
173  //delay(1200);
174  while(1){
175 
176  lock();
177  //Serial.println("L data Lock");
178  thisPage->sendHeartbeat();
179  thisPage->SendAllLabels();
180  thisPage->SendAllValues();
181  if (thisPage->updatePID){
182  for(int i=0; i<MAX_POSSIBLE_MOTORS; i++){
183  thisPage-> SendPIDValues(i);
184  thisPage->SendSetpoint(i);
185  }
186  thisPage->updatePID=false;
187  }
188  //while (thisPage->sendPacketFromQueue());
189  unlock();
190 
191  }
192 }
193 
194 void packetTXTask(void *param){
195  while(1);
196 }
197 
199  //ESP_LOGI("WebPage::WebPage","WebPage Init..");
200  server.begin();
201  //Serial.println("HTTP server started");
202 //
203  /*
204  server.on("/", 0b00000001, [](AsyncWebServerRequest *request){
205 
206  lock();
207  //Serial.println("L text/html Lock");
208  request->send(200, "text/html",myHTML );
209  unlock();
210 
211  });*/
212  valuesSem = xSemaphoreCreateMutex();
213  xSemaphoreGive(valuesSem);
214  ws.onEvent(onWsEvent);
215  server.addHandler(&ws);
216  server.on("/pidvalues", 0b00000001, [](AsyncWebServerRequest *request){
217 
218  lock();
219  //Serial.println("L text/javascript Lock");
220 
221  Serial.print("args: ");
222  Serial.println(request->args());
223  for(int i=0; i<request->args(); i++){
224  String key = request->argName(i);
225  if (key.length()>=2){
226  int32_t index = key.substring(1).toInt()-1;
227  if (index!=-1 && index<MAX_POSSIBLE_MOTORS && Motor::list[index] != NULL){
228 
229  float value = request->arg(i).toFloat();
230  if (key.charAt(0)=='p'){
231  Serial.print("Setting P Gain ");
232  Serial.print(index);
233  Serial.print(":\t");
234  Serial.println(value);
235  Motor::list[index]->setGainsP(value);
236  }
237  if (key.charAt(0)=='i'){
238  Serial.print("Setting I Gain ");
239  Serial.print(index);
240  Serial.print(":\t");
241  Serial.println(value);
242  Motor::list[index]->setGainsI(value);
243  }
244  if (key.charAt(0)=='d'){
245  Serial.print("Setting D Gain ");
246  Serial.print(index);
247  Serial.print(":\t");
248  Serial.println(value);
249  Motor::list[index]->setGainsD(value);
250  }
251  }
252  }
253  }
254  String pidvals="[";
255  for(int i=0; i<MAX_POSSIBLE_MOTORS; i++){
256 
257  if(Motor::list[i] != NULL){
258  if (i!=0) pidvals+=",";
259  pidvals+="["+String(Motor::list[i]->getGainsP())+
260  ","+String(Motor::list[i]->getGainsI())+
261  ","+String(Motor::list[i]->getGainsD())+"]";
262  }
263  }
264  pidvals += "]";
265  request->send(200, "text/html", pidvals);
266  unlock();
267 
268  });
269  server.on("/*", 0b00000001, [](AsyncWebServerRequest *request){
270  String url = request->url();
271  lock();
272  //Serial.println("L text/html Lock");
273  Serial.println(url);
274  // lookup our file
275  if (url == "/") url = "/index.html";
276  for(int i=0; i<static_files_manifest_count; i++){
277  if(url.equals(static_files_manifest[i].name)){
278  // This is turbo broken?
279  request->send(200, (char*)static_files_manifest[i].mime, static_files_manifest[i].data);
280 
281  }
282 
283  }
284  unlock();
285 
286  });
287 
288 
289  xTaskCreatePinnedToCore(
290  updateTask, /* Function to implement the task */
291  "UpdateTask", /* Name of the task */
292  8192 * 8, /* Stack size in words */
293  NULL, /* Task input parameter */
294  4, /* Priority of the task */
295  &thisPage->updateTaskHandle, /* Task handle. */
296  1); /* Core where the task should run */
297 
298 
299 
300 
301 }
302 
303 float WebPage::getSliderValue(uint32_t number){
304  //Serial.println("Index:\t"+String(number));
305  if (number>3) return 0.0;
306  return sliders[number];
307 }
309  return joystick.angle;
310 }
312  return joystick.mag;
313 }
315  return joystick.xpos;
316 }
318  return joystick.ypos;
319 }
321 
322 // Serial.print("\nJoystick Update");
323 // Serial.print(" X pos:\t"+String(joystick.xpos));
324 // Serial.print(" Y pos:\t"+String(joystick.ypos));
325 // Serial.print(" Angle:\t"+String(joystick.angle));
326 // Serial.print(" Dist:\t"+String(joystick.mag));
327 
328  return &joystick;
329 }
330 
331 void WebPage::setSliderValue(uint32_t number, float value){
332  if (number<4) thisPage->sliders[number]=value;
333 }
334 
335 void WebPage::setJoystickValue(float xpos, float ypos, float angle, float mag){
336  angle-=(PI/2.0);
337  joystick.xpos = cos(angle)*mag;
338  joystick.ypos = sin(angle)*mag;
339  joystick.angle = 180*angle/PI;
340  joystick.mag = mag;
341 }
342 
343 void WebPage::setValue(String name, float data){
344  while (xSemaphoreTake(valuesSem,( TickType_t ) 10)==false);
345  if(abs(data)<0.00001)
346  data=0;
347  for(int i=0; i<numValues; i++){
348  if (values[i].used){ // compare in use slots
349 
350  if (values[i].name==name){ // check label
351  if(values[i].value!=data){ // Has the value itself changed?
352  //Serial.println("Update '"+name+"' "+String(data));
353  values[i].value = data; // update data
354  values[i].valueDirty=true;
355  }
356  xSemaphoreGive(valuesSem);
357  return;
358  }
359  } else {
360  //
361  Serial.println("Create '"+name+"' "+String(i));
362  values[i].used=true;
363  values[i].name = name;
364  values[i].value = data;
365  values[i].valueDirty=true;
366  values[i].labelDirty=true;
367  values[i].buffer=0;
368  numValuesUsed++;
369  xSemaphoreGive(valuesSem);
370  return;
371  }
372  }
373 }
374 
376  for(int i=0; i<numValues; i++){
377  if (values[i].used && values[i].labelDirty) return true;
378  }
379  return false;
380 }
381 
383  for(int i=0; i<numValues; i++){
384  if (values[i].used && values[i].valueDirty) return true;
385  }
386  return false;
387 }
388 
389 
391  if (ws.count()==0) return false;
392  if (dirtyValues()==false) return false;
393  uint8_t * packetBuffer = new uint8_t[numValues*8]; // Allocate a new one 8 bytes per slot max
394 
395  // Allocate float and int access arrays
396  uint32_t *bufferAsInt32=(uint32_t*)packetBuffer;
397  float *bufferAsFloat=(float*)packetBuffer;
398 
399  bufferAsInt32[0]=0x0000001e; // packet id update all
400 
401 
402  uint32_t bufferItemCount=0; // Count the values in this update.
403  for(int i=0; i<numValues; i++){
404  if (values[i].used){ // Is this slot in use?
405  if (values[i].valueDirty){ // Has this value changed
406  //values[i].valueDirty=false; //reset change flag
407  bufferAsInt32[(bufferItemCount+1)*2] = i; // Index of this specific value
408  bufferAsFloat[(bufferItemCount+1)*2+1] = values[i].value; // The float value
409  bufferItemCount++;
410  }
411  }
412  }
413 
414  bufferAsInt32[1]=bufferItemCount; // Record the number of elements at position 1 after the packet id
415  uint32_t packetLength = (bufferItemCount+1)*8; // 8 byte header + each int/float pair
416 
417 
418  if (bufferItemCount>0){
419  // We have at least 1 item, lets send a packet.
420  if (sendPacket(packetBuffer,packetLength)){
421  // Packet sucessfully sent, clear dirty flags.
422  for(int i=0; i<numValues; i++) values[i].valueDirty=false;
423  return true;
424  } else {
425  return false;
426  }
427  }
428 
429  return false; // no update sent
430  /*
431  if(valueToSendThisLoop>=numValuesUsed)
432  valueToSendThisLoop=0;
433  int i= valueToSendThisLoop;
434  if(values[i].used){
435  if(values[i].buffer)
436  delete values[i].buffer;
437  values[i].buffer=new uint8_t[labelbuflen];
438  sendLabelUpdate(i,values[i].buffer);
439  sendValueUpdate(i,values[i].buffer);
440 
441  uint32_t datalen = 12+values[i].name.length()+1;
442  for(int j=datalen;j<datalen+4;j++)values[i].buffer[j]=0;
443  datalen += (4-(datalen%4)); // round up to multiple of 4
444  if (datalen>=labelbuflen) datalen=labelbuflen;
445  //datalen=labelbuflen;
446  // Serial.print("\r\nSending Bytes "+String(datalen)+" [");
447  // for(int j=0;j<datalen;j++){
448  //
449  // Serial.print(", "+String(values[i].buffer[j])+" ");
450  //
451  // }
452  // Serial.print("]");
453  if (ws.availableForWriteAll())
454  //txPacketCount++;
455  ws.binaryAll(values[i].buffer, datalen);
456  //delay(5);
457  //Serial.println("Updating "+values[i].name);
458  }
459  valueToSendThisLoop++;
460  return values[i].used;
461  */
462 }
463 
464 
466  // are any of our labels dirty?
467  if (dirtyLabels()==false) return false; // No? don't continue.
468  if (xSemaphoreTake(valuesSem,( TickType_t ) 10)==false) return false;
469  uint32_t lengthPredict = labelBufferSize;
470  uint8_t * labelBuffer = new uint8_t[lengthPredict]; // Allocate a buffer
471 
472  uint32_t *bufferAsInt32=(uint32_t*)labelBuffer;
473  float *bufferAsFloat=(float*)labelBuffer;
474  char *bufferAsChar=(char*)labelBuffer;
475 
476  bufferAsInt32[0]=0x0000001d; // packet id update all labels
477  bufferAsInt32[1]=0; // num labels
478 
479  uint32_t bufferItemCount=0; // Count the values in this update.
480  for(int i=0; i<numValues; i++){
481  if (values[i].used){ // Is this slot in use?
482  if (values[i].labelDirty){ // Has this value changed
483  //Serial.println("Dirty: '"+String(values[i].name)+"' ("+String(i)+")");
484  bufferAsInt32[(bufferItemCount+1)*3] = i; // Index of this specific label
485  bufferAsInt32[(bufferItemCount+1)*3 + 1] = 0; // offset.
486  bufferAsInt32[(bufferItemCount+1)*3 + 2] = values[i].name.length()+1; // length of this specific label. +1 for null terminator
487  bufferItemCount++;
488  }
489  }
490  }
491 
492  if (bufferItemCount==0) {
493  xSemaphoreGive(valuesSem);
494  return false; // Nothing to update, bail.
495  }
496  // Write number of labels.
497  bufferAsInt32[1]=bufferItemCount;
498 
499  uint32_t startOfStringData=(bufferItemCount+1)*12;
500  uint32_t stringOffset = 0;
501 
502  bufferAsInt32[2]=startOfStringData;
503  //Serial.println("Item Count: '"+String(bufferItemCount)+"'");
504  //Serial.println("String Data Start: '"+String(startOfStringData)+"'");
505  // Load changed strings into buffer.
506  // update offsets as you load them in
507  for(int i=0; i<bufferItemCount; i++){
508  uint32_t index = bufferAsInt32[(i+1)*3];
509  uint32_t length = bufferAsInt32[(i+1)*3 + 2];
510  if (startOfStringData+stringOffset+values[index].name.length() > labelBufferSize){
511  //Serial.println("Strings won't fit into buffer!");
512  //Serial.println("target: "+String(startOfStringData+stringOffset+values[index].name.length()));
513  //Serial.println("limit: "+String(labelBufferSize));
514  xSemaphoreGive(valuesSem);
515  return false;
516  }
517  //Serial.print("Processing #"+String(i)+" len: "+String(length)+"... ");
518  bufferAsInt32[(i+1)*3 + 1] = stringOffset;
519  memcpy(&bufferAsChar[startOfStringData+stringOffset],values[index].name.c_str(),length);
520  stringOffset+=length;
521  //values[index].labelDirty=false;
522  //Serial.println("Done! packet offset: "+String(startOfStringData+stringOffset));
523 
524  }
525  //Serial.println("Total Bytes in Buf: '"+String(startOfStringData+stringOffset)+"'");
526  //Serial.println("Total Bytes Predicted: '"+String(lengthPredict)+"'");
527  uint32_t packetLength = startOfStringData+stringOffset;
528  packetLength += (4-(packetLength%4));
529  xSemaphoreGive(valuesSem);
530  if (bufferItemCount>0){
531  // We have at least 1 item, lets send a packet.
532  if (sendPacket(labelBuffer,packetLength)){
533  // We've sent the data, clear ditry flags
534  for(int i=0; i<numValues; i++) values[i].labelDirty=false;
535  return true;
536  }
537  }
538  return false;
539 }
540 
541 void WebPage::sendValueUpdate(uint32_t index,uint8_t *buffer){
542  if(index>numValues-1) return;
543 // if (!values[index].used) return;
544 // if (values[index].oldValue==values[index].value) return;
545 
546  uint32_t *bufferAsInt32=(uint32_t*)buffer;
547  float *bufferAsFloat=(float*)buffer;
548  bufferAsInt32[0]=0x00000010;
549  bufferAsInt32[1]=index;
550  bufferAsFloat[2]=values[index].value;
551 }
552 
553 
554 void WebPage::sendLabelUpdate(uint32_t index,uint8_t *buffer){
555  if(index>numValues-1) return;
556 // if (!values[index].used) return;
557 // if(!values[index].valueDirty) return;
558  values[index].valueDirty=false;
559 
560  // Write out the string to the buffer. offset by 12 bytes.
561  for(int i=0;i<values[index].name.length();i++){
562  buffer[i+12]=values[index].name.c_str()[i];
563  }
564  buffer[values[index].name.length()+12]=0;
565 
566 
567 }
568 
569 
570 void WebPage::newButton(String url, void (*handler)(String), String label, String description){
571 
572 }
573 
574 
575 void WebPage::valueChanged(String name, float value){
576  //ESP_LOGI("WebPage::valueChanged","Got async change for '%s'",String2Chars(name)); //
577  setValue(name,value);
578 }
579 
581  for(int i=0; i<numValues; i++){
582  if (values[i].used){ // Is this slot in use?
583  values[i].labelDirty=true;
584  values[i].valueDirty=true;
585  }
586  }
587 }
588 void WebPage::setHeartbeatUUID(uint32_t uuid){
589  _heartbeat_uuid=uuid;
590 }
591 
593  if (_heartbeat_uuid==0) return false;
594  uint8_t * heartbeatBuffer = new uint8_t[8];
595  uint32_t *bufferAsInt32=(uint32_t*)heartbeatBuffer;
596  bufferAsInt32[0]=0x00000050;
597  bufferAsInt32[1]=_heartbeat_uuid;
598  _heartbeat_uuid=0;
599  return sendPacket(heartbeatBuffer,8);
600 }
601 
602 void WebPage::printToWebConsole(String data){
603  uint32_t length = data.length()+1;
604  uint32_t packetLength = length + 8 + (4-(length%4));
605  uint8_t * consolePacket = new uint8_t[packetLength];
606  uint32_t *bufferAsInt32=(uint32_t*)consolePacket;
607 
608  bufferAsInt32[0]=0x11;
609  bufferAsInt32[1]=length;
610  data.toCharArray((char *)(consolePacket+8), length);
611  sendPacket(consolePacket,packetLength);
612 
613 
614 }
615 
616 void WebPage::UpdatePIDValues(uint32_t motor,float p, float i, float d){
617  if (motor<MAX_POSSIBLE_MOTORS && Motor::list[motor] != NULL){
618  Motor::list[motor]->setGainsP(p);
619  Motor::list[motor]->setGainsI(i);
620  Motor::list[motor]->setGainsD(d);
621  }
622 }
623 
624 void WebPage::UpdateSetpoint(uint32_t motor, float setpoint){
625  if (motor<MAX_POSSIBLE_MOTORS && Motor::list[motor] != NULL){
626  Motor::list[motor]->setSetpoint(setpoint);
627  }
628 }
629 
630 bool WebPage::SendPIDValues(uint32_t motor){
631  //pidsetBuffer;
632  //return false;
633  if (ws.count()==0) return false;
634 
635  if (motor<MAX_POSSIBLE_MOTORS && Motor::list[motor] != NULL){
636  uint8_t * pidsetBuffer = new uint8_t[20];
637  uint32_t *bufferAsInt32=(uint32_t*)pidsetBuffer;
638  float *bufferAsFloat=(float*)pidsetBuffer;
639  bufferAsInt32[0]=0x00000060;
640  bufferAsInt32[1]=motor;
641  bufferAsFloat[2]=Motor::list[motor]->getGainsP();
642  bufferAsFloat[3]=Motor::list[motor]->getGainsI();
643  bufferAsFloat[4]=Motor::list[motor]->getGainsD();
644  return sendPacket(pidsetBuffer,20);
645  }
646  return false;
647 
648 }
649 
650 bool WebPage::SendSetpoint(uint32_t motor){
651  //setpointsetBuffer;
652  //return false;
653 
654 
655  if (motor<MAX_POSSIBLE_MOTORS && Motor::list[motor] != NULL){
656  uint8_t * setpointsetBuffer = new uint8_t[12];
657  uint32_t *bufferAsInt32=(uint32_t*)setpointsetBuffer;
658  float *bufferAsFloat=(float*)setpointsetBuffer;
659  bufferAsInt32[0]=0x00000061;
660  bufferAsInt32[1]=motor;
661  bufferAsFloat[2]=Motor::list[motor]->getCurrentDegrees();
662  return sendPacket(setpointsetBuffer,12);
663  }
664  return false;
665 
666 }
667 
668 
669 bool WebPage::sendPacket(unsigned char* packet, uint32_t length){
670  if (ws.enabled() && ws.availableForWriteAll()){
671  ws.binaryAll(packet,length);
672  txPacketCount++;
673  delete packet;
674  return true;
675  }
676  //binaryAll MALLOCs memory and MEMCPYs packet into it's own buffer.
677  // this does not happen in another thread, it happens here.
678  //once it returns we can dealloc.
679  delete packet;
680  return false;
681 }
static WebPage * thisPage
Definition: WebPage.cpp:17
static const int static_files_manifest_count
Definition: static.h:4741
telemetryValue values[numValues]
Definition: WebPage.h:50
const char * name
Definition: static.h:3
bool SendSetpoint(uint32_t motor)
Definition: WebPage.cpp:650
float getGainsI()
Definition: Motor.h:461
String name
Definition: WebPage.h:17
float value
Definition: WebPage.h:18
void setSetpoint(float newTargetInDegrees)
Definition: Motor.h:366
void UpdateSetpoint(uint32_t motor, float setpoint)
Definition: WebPage.cpp:624
void setSliderValue(uint32_t number, float value)
Definition: WebPage.cpp:331
uint8_t * buffer
Definition: WebPage.h:22
AsyncWebSocket ws("/test")
int numValuesUsed
Definition: WebPage.h:51
void newButton(String url, void(*handler)(String), String label, String description)
Definition: WebPage.cpp:570
float angle
Definition: WebPage.h:10
JoyData joystick
Definition: WebPage.h:56
void unlock()
Definition: WebPage.cpp:165
uint32_t rxPacketCount
Definition: WebPage.h:58
void valueChanged(String name, float value)
Definition: WebPage.cpp:575
void printToWebConsole(String data)
Definition: WebPage.cpp:602
TaskHandle_t updateTaskHandle
Definition: WebPage.h:59
float getSliderValue(uint32_t number)
Definition: WebPage.cpp:303
void onWsEvent(AsyncWebSocket *server, AsyncWebSocketClient *client, AwsEventType type, void *arg, uint8_t *data, size_t len)
Definition: WebPage.cpp:30
void setGainsI(float i)
Definition: Motor.cpp:439
void sendValueUpdate(uint32_t index, uint8_t *buffer)
Definition: WebPage.cpp:541
void setValue(String name, float data)
Definition: WebPage.cpp:343
void setGainsP(float p)
Definition: Motor.cpp:431
float xpos
Definition: WebPage.h:8
float sliders[numSliders]
Definition: WebPage.h:49
long timeSinceLastSend
Definition: WebPage.cpp:26
bool sendHeartbeat()
Definition: WebPage.cpp:592
static char stringBuffer[200]
Definition: WebPage.cpp:18
float getJoystickAngle()
Definition: WebPage.cpp:308
void setGainsD(float d)
Definition: Motor.cpp:447
void packetTXTask(void *param)
Definition: WebPage.cpp:194
WebPage()
Definition: WebPage.cpp:136
float getJoystickX()
Definition: WebPage.cpp:314
static bool lockOutSending
Definition: WebPage.cpp:24
#define numValues
Definition: WebPage.h:26
float getGainsP()
Definition: Motor.h:455
SemaphoreHandle_t valuesSem
Definition: WebPage.h:82
void UpdatePIDValues(uint32_t motor, float p, float i, float d)
Definition: WebPage.cpp:616
void initalize()
Definition: WebPage.cpp:198
#define MAX_POSSIBLE_MOTORS
Definition: Motor.h:13
bool SendPIDValues(uint32_t motor)
Definition: WebPage.cpp:630
bool labelDirty
Definition: WebPage.h:21
bool sendPacket(unsigned char *packet, uint32_t length)
Definition: WebPage.cpp:669
bool dirtyValues()
Definition: WebPage.cpp:382
float getCurrentDegrees()
Definition: Motor.cpp:568
float getJoystickMagnitude()
Definition: WebPage.cpp:311
bool SendAllLabels()
Definition: WebPage.cpp:465
float getJoystickY()
Definition: WebPage.cpp:317
#define numSliders
Definition: WebPage.h:25
AsyncWebServer server(80)
void sendLabelUpdate(uint32_t index, uint8_t *buffer)
Definition: WebPage.cpp:554
float ypos
Definition: WebPage.h:9
float mag
Definition: WebPage.h:11
bool SendAllValues()
Definition: WebPage.cpp:390
bool updatePID
Definition: WebPage.h:34
bool dirtyLabels()
Definition: WebPage.cpp:375
uint32_t _heartbeat_uuid
Definition: WebPage.h:94
static Motor * list[MAX_POSSIBLE_MOTORS]
Definition: Motor.h:200
bool valueDirty
Definition: WebPage.h:20
void markAllDirty()
Definition: WebPage.cpp:580
void setJoystickValue(float xpos, float ypos, float angle, float mag)
Definition: WebPage.cpp:335
#define labelBufferSize
Definition: WebPage.h:27
char * String2Chars(String str)
Definition: WebPage.cpp:130
void setHeartbeatUUID(uint32_t uuid)
Definition: WebPage.cpp:588
float getGainsD()
Definition: Motor.h:467
void updateTask(void *param)
Definition: WebPage.cpp:172
JoyData * getJoystickData()
Definition: WebPage.cpp:320
uint32_t txPacketCount
Definition: WebPage.h:57
static const PACKED_FILE static_files_manifest[]
Definition: static.h:4766
bool isSafeToSend()
Definition: WebPage.cpp:152
void lock()
Definition: WebPage.cpp:158