View Single Post
Old 06-16-2017, 11:43 AM   #126 (permalink)
skybolt
deviant
 
Join Date: Oct 2016
Location: Seattle, WA
Posts: 69

s2k - '02 Honda s2000
Thanks: 12
Thanked 47 Times in 35 Posts
Updated JSON function

Here is the updated JSON function, in zip form and in CODE block

Code:
void doOutputJSON(void) //skybolt added json output function
{
  digitalWrite(LED_BUILTIN, LOW);
  digitalWrite(LED_BUILTIN, HIGH);   // turn the LED on (HIGH is the voltage level)


  uint64_t instFuelEcon;
  uint64_t tankFuelEcon;
  uint64_t tankFuelEcon53;
  //if->then using timerChecker allows for changing the subtitle to show multiple lines of information
  uint32_t timerChecker = cycles0(); //wastes 20 bytes but ensures all lines will change on the same cycle

  unsigned long reserveQuantity = SWEET64(prgmReserveFuelRemaining, 0);
#ifdef usePartialRefuel
  unsigned long tankSize = eepromReadVal(pTankSizeIdx) + eepromReadVal(pRefuelSizeIdx);
#else // usePartialRefuel
  unsigned long tankSize = eepromReadVal(pTankSizeIdx);
#endif // usePartialRefuel

  text::stringOut(devLogSerial, PSTR("\n\n[")); // begin JSON payload
  

  // first graph, fuel
  text::stringOut(devLogSerial, PSTR("{\"title\":\""));
    if (reserveQuantity == 0) text::stringOut(devLogSerial, PSTR("fumes remaining, ")); // fumes left
  else doOutputNumberJSON(prgmReserveFuelRemaining, 0, 3, PSTR(" \xfbgal\xfcL\xfd remaining, ")); // reserve remaining fuel left
  doOutputNumberJSON(prgmBingoFuelRemaining, 0, 3, PSTR(" \xfbgal\xfcL\xfd e-reserve\",\n")); // bingo remaining fuel left
//  doOutputNumberJSON(instantIdx, tEngineSpeed, 0, PSTR(" RPM\",\n")); // rpm to test latency only vs tachometer and LCD vs raspi indicator (expect 2x looptime)
if (  (timerChecker / 100) % 8000 > 4000 ) {
  text::stringOut(devLogSerial, PSTR("\"subtitle\":\"fuel used: "));
  
  doOutputNumberJSON(currentIdx, tFuelUsed, 3, PSTR(" trip \xfbgal\xfcL\xfd; ")); // current trip fuel used
  doOutputNumberJSON(tankIdx, tFuelUsed, 3, PSTR(" tank \xfbgal\xfcL\xfd; ")); // tank trip fuel used
  doOutputNumberJSON(instantIdx, tFuelRate, 3, PSTR(" using \xfbgal\xfcL\xfd/hr\",\n")); // current rate of fuel burn in units/time

} else {
  text::stringOut(devLogSerial, PSTR("\"subtitle\":\"eco stats: "));
#ifdef trackIdleEOCdata
  doOutputNumberJSON(eocIdleTankIdx, tFuelUsed, 3, PSTR(" \xfbgal\xfcL\xfd used@idle, "));
  doOutputNumberJSON(eocIdleTankIdx, tDistance, 1, PSTR(" \xfbmi\xfckm\xfd fuel cut\",\n"));
#else
  if (reserveQuantity == 0) text::stringOut(devLogSerial, PSTR("fumes remaining, ")); // fumes left
  else doOutputNumberJSON(prgmReserveFuelRemaining, 0, 3, PSTR(" \xfbgal\xfcL\xfd remaining, ")); // reserve remaining fuel left
  doOutputNumberJSON(prgmBingoFuelRemaining, 0, 3, PSTR(" \xfbgal\xfcL\xfd e-reserve\",\n")); // bingo remaining fuel left
#endif
}

  reserveQuantity = eepromReadVal(pTankBingoIdx);

  text::stringOut(devLogSerial, PSTR("\"ranges\":[")); //ranges do not have to be in order, d3js libraries will auto sort, so you can make it easier to read the code by changing the order
  doOutputNumberJSON(tankSize, 3, PSTR(",")); // largest, full tank size (e.g, 13.8 g)
  doOutputNumberJSON(tankSize - reserveQuantity, 3, PSTR(",")); // full tank less reserve (e.g.13.8g - 2.2g = 11.6g)
  doOutputNumberJSON(reserveQuantity, 3, PSTR("],\n")); // reserve amount (e.g. 2.2g)

  text::stringOut(devLogSerial, PSTR("\"measures\":["));
  doOutputNumberJSON(prgmReserveFuelRemaining, 0, 3, PSTR(",")); // reserve remaining fuel left
  doOutputNumberJSON(prgmRemainingFuel, 0, 3, PSTR("],\n")); // total remaining fuel left

  text::stringOut(devLogSerial, PSTR("\"markers\":["));
  doOutputNumberJSON(instantIdx, tFuelRate, 3, PSTR("]},\n\n")); // current rate of fuel burn in units/time

  // second graph, distance  
  text::stringOut(devLogSerial, PSTR("{\"title\":\""));
  doOutputNumberJSON(prgmReserveDTE, tankIdx, 2, PSTR("\xfbmi\xfckm\xfd to e, ")); // distance to bingo
  doOutputNumberJSON(prgmBingoDTE, tankIdx, 2, PSTR(" \xfbmi\xfckm\xfd e-reserve\",\n")); // distance to fully empty tank from bingo

if (  (timerChecker / 100) % 8000 > 4000 ) {
//   text::stringOut(devLogSerial, PSTR("\"subtitle\":\"trip/tank distance: "));
//   doOutputNumberJSON(currentIdx, tDistance, 2, PSTR(" \xfbmi\xfckm\xfd/")); // current trip distance
//   doOutputNumberJSON(tankIdx, tDistance, 2, PSTR(" \xfbmi\xfckm\xfd\",\n")); // current trip distance
  text::stringOut(devLogSerial, PSTR("\"subtitle\":\""));
  doOutputNumberJSON(currentIdx, tDistance, 2, PSTR(" \xfbmi\xfckm\xfd trip distance, ")); // current trip distance
  doOutputNumberJSON(tankIdx, tDistance, 2, PSTR(" \xfbmi\xfckm\xfd tank distance\",\n")); // current trip distance

  } else {
  text::stringOut(devLogSerial, PSTR("\"subtitle\":\""));
  doOutputNumberJSON(prgmFindReserveRange, tankIdx, 2, PSTR(" \xfbmi\xfckm\xfd safe range, ")); // reserve range
  doOutputNumberJSON(prgmFindRange, tankIdx, 2, PSTR(" \xfbmi\xfckm\xfd dry range\",\n")); // distance to fully empty tank
  }

  text::stringOut(devLogSerial, PSTR("\"ranges\":["));
  doOutputNumberJSON(prgmFindRange, tankIdx, 1, PSTR(",")); // maximum range
  doOutputNumberJSON(prgmFindReserveRange, tankIdx, 1, PSTR(",")); // range 2, safe range
  doOutputNumberJSON(prgmFindHalfReserveRange, tankIdx, 1, PSTR("],\n")); // range 3, half of safe range

  text::stringOut(devLogSerial, PSTR("\"measures\":["));
  doOutputNumberJSON(prgmFindBingoRange, tankIdx, 2, PSTR("],\n")); // shows miles of e-reserve in bar form

  text::stringOut(devLogSerial, PSTR("\"markers\":["));
  doOutputNumberJSON(tankIdx, tDistanceToEmpty, 2, PSTR("]},\n\n")); // line is distance to empty





  // third graph, econ
  text::stringOut(devLogSerial, PSTR("{\"title\":\"")); //\xfbgal\xfcL\xfd/	
  #ifdef useDragRaceFunction
//   text::stringOut(devLogSerial, PSTR("("));  
//   doOutputNumberJSON(lastAccelTestStatus, 3, PSTR(") "));
//   doOutputNumberJSON(msInstantIdx, tSpeed, 3, PSTR(" ")); // current fuel economy

  // if (accelerationFlags & accelTestTriggered) {  //display if we are waiting for a drag start  
  // there was a bug in some of the drag cancel logic when using Adafruit. I disabled some statements
  // to get it to work. (Was tripping at 0.718 or 0.0718 seconds (don't remember exact digits)
  //some kind of bit mask; full and half-speed seem to be backwards (0 means tripped)
  //unclear on syntax for building if/then statements
    //accelerationFlags & accelTestTriggered
    // 120, waiting
    // 184, testing. 
    // 176, distance met. 
    // 160, distance and half-speed met. (Full speed then meets all conditions, test ends)
    // 168 half-speed met. (not distance)
    // 136 full-speed met. (Meeting distance then meets all three conditions, race ends). 
    // what the hell is 156? Did this actually come up? 
	// lastAccelTestStatus = 120; //use to force trigger
	
  if (lastAccelTestStatus == 120) {  //display if we are waiting for a drag start  
  text::stringOut(devLogSerial, PSTR("Drag Ready ...\",\n"));
  //did these in reverse order when i was checking for bits, with numbers order is irrelevant
  } else if (lastAccelTestStatus == 136) { //display once test started //too hard to reverse engineer and/or/contains | &, from numeric tests. Numbers work fine. 
  text::stringOut(devLogSerial, PSTR("Full speed reached ...\",\n"));  
  } else if (lastAccelTestStatus == 168) { //display at half speed
  text::stringOut(devLogSerial, PSTR("Half-speed reached ...\",\n")); 
  } else if (lastAccelTestStatus == 176) { //display at half speed
  text::stringOut(devLogSerial, PSTR("Distance reached ...\",\n"));  
  } else if (lastAccelTestStatus == 184) { //display once test started
  text::stringOut(devLogSerial, PSTR("Testing ...\",\n"));    
  } else if ( lastAccelTestStatus == 160) { //display once test started
  text::stringOut(devLogSerial, PSTR("Half-speed and distance reached ...\",\n"));  
  } else { //else not racing or waiting, go to normal
  text::stringOut(devLogSerial, PSTR("trip/tank/inst: ")); //\xfbgal\xfcL\xfd/	
  doOutputNumberJSON(currentIdx, tFuelEcon, 3, PSTR("/ ")); // current fuel economy
  doOutputNumberJSON(tankIdx, tFuelEcon, 3, PSTR("/ ")); // tank fuel economy
  reserveQuantity = doCalculate(instantIdx, tFuelEcon);
  if (reserveQuantity > 9999999) text::stringOut(devLogSerial, PSTR("infinite\",\n"));
  else doOutputNumberJSON(instantIdx, tFuelEcon, 3, PSTR("\",\n")); // instantaneous fuel economy
 }
  
  if ( ( ((timerChecker / 100) % 12000) > 8000) ) { 
  //1 & 2 seconds display
  text::stringOut(devLogSerial, PSTR("\"subtitle\":\"accel time: 0-"));
  doOutputNumberJSON(eepromReadVal(pDragSpeedIdx) / 2, 0, PSTR("/"));
  doOutputNumberJSON(eepromReadVal(pDragSpeedIdx), 0, PSTR(": "));
  doOutputNumberJSON(dragHalfSpeedIdx, tAccelTestTime, 2, PSTR("/")); // 0-30 time
  doOutputNumberJSON(dragFullSpeedIdx, tAccelTestTime, 2, PSTR(", ")); // 0-60 time
  doOutputNumberJSON(dragDistanceIdx, tDistance * 1, 2, PSTR("\xfbmi\xfckm\xfd in ")); // trap distance
  doOutputNumberJSON(dragDistanceIdx, tAccelTestTime, 2, PSTR(" @")); // trap time
  doOutputNumberJSON(dragDistanceIdx, tSpeed, 3, PSTR("\xfbmph\xfckph\xfd; ")); // trap speed
  doOutputNumberJSON(dragHalfSpeedIdx, tEstimatedEnginePower, 0, PSTR("\xfbhp\xfckW\xfd @")); // estimated engine power
  doOutputNumberJSON(dragHalfSpeedIdx, tDragSpeed, 0, PSTR("\xfbmph\xfckph\xfd\",\n")); // max speed
  } else { 
//"subtitle":"accel fuel: 0.000 (0.00mpg) to 15, 0.000 (0.00mpg) to 30; 0.000 (0.000) to 0",
  text::stringOut(devLogSerial, PSTR("\"subtitle\":\"accel fuel: "));
  
//   this dumps the flag values to the screen  
//   text::stringOut(devLogSerial, PSTR("("));
//   doOutputNumberJSON(lastAccelTestStatus, 3, PSTR(" ")); 
//   text::stringOut(devLogSerial, PSTR(" "));
//   doOutputNumberJSON(accelTestActive, 3, PSTR(" ")); //0.128
//   text::stringOut(devLogSerial, PSTR(" "));
//   doOutputNumberJSON(accelTestTriggered, 3, PSTR(" ")); //0.064
//   text::stringOut(devLogSerial, PSTR(" "));
//   doOutputNumberJSON(accelTestFullSpeed, 3, PSTR(" ")); //0.032
//   text::stringOut(devLogSerial, PSTR(" "));
//   doOutputNumberJSON(accelTestHalfSpeed, 3, PSTR(" ")); //0.016
//   text::stringOut(devLogSerial, PSTR(" "));
//   doOutputNumberJSON(accelTestDistance, 3, PSTR(" ")); //0.008
//   text::stringOut(devLogSerial, PSTR(" "));
//   doOutputNumberJSON(accelTestCancelled, 3, PSTR(" ")); //0.004
//   text::stringOut(devLogSerial, PSTR(" "));
//   doOutputNumberJSON(accelTestFinished, 3, PSTR(") ")); //0.002
  if ( ( ((timerChecker / 100) % 12000) > 4000) ) { 
  doOutputNumberJSON(dragHalfSpeedIdx, tFuelUsed, 3, PSTR("\xfbga\xfcL\xfd to ")); // 0-half fuel
  doOutputNumberJSON(eepromReadVal(pDragSpeedIdx) / 2, 0, PSTR(", ")); // 0-half speed
  doOutputNumberJSON(dragFullSpeedIdx, tFuelUsed, 3, PSTR("\xfbga\xfcL\xfd to ")); // 0-full fuel
  doOutputNumberJSON(eepromReadVal(pDragSpeedIdx), 0, PSTR(", ")); // 0-full speed
  doOutputNumberJSON(dragDistanceIdx, tFuelUsed, 3, PSTR("\xfbga\xfcL\xfd to ")); //trap fuel
  doOutputNumberJSON(dragDistanceIdx,  tDistance * 1, 2, PSTR("\xfbmi\xfckm\xfd\",\n")); // "to [trap distance]"  \xfbft\xfcm\xfd; 
} else {
  doOutputNumberJSON(dragHalfSpeedIdx, tFuelEcon, 3, PSTR("\xfbmpg\xfcL100\xfd to ")); // 0-30 mpg
  doOutputNumberJSON(eepromReadVal(pDragSpeedIdx) / 2, 0, PSTR(", ")); // 0-half speed
  doOutputNumberJSON(dragFullSpeedIdx, tFuelEcon, 3, PSTR("\xfbmpg\xfcL100\xfd to ")); // 0-60 mpg
  doOutputNumberJSON(eepromReadVal(pDragSpeedIdx), 0, PSTR(", ")); // 0-60 speed
  doOutputNumberJSON(dragDistanceIdx, tFuelEcon, 3, PSTR("\xfbmpg\xfcL100\xfd to ")); //trap mpg 
  doOutputNumberJSON(dragDistanceIdx,  tDistance * 1, 2, PSTR("\xfbmi\xfckm\xfd\",\n")); // "to [trap distance]"  \xfbft\xfcm\xfd; 

}

}  

#else
  text::stringOut(devLogSerial, PSTR("\"subtitle\":\"[this space intentionally left blank]\",\n"));
#endif

  text::stringOut(devLogSerial, PSTR("\"ranges\":[18,24,"));
//  text::stringOut(devLogSerial, PSTR("\"ranges\":["));
//  doOutputNumberJSON(2 * fuelEconomyFIRvalue / 3, 3, PSTR(",")); // 2/3 averaged instantaneous fuel economy over time
//  doOutputNumberJSON(fuelEconomyFIRvalue, 3, PSTR(",")); // averaged instantaneous fuel economy over time
  doOutputNumberJSON(
  min(
  max(40000,  doCalculate(instantIdx, tFuelEcon))
  , 999000),
  3, PSTR("],\n")); // set scale at 40mpg or instant econ up to 999 mpg. Folks like to watch their mpg meter go to extremes

  text::stringOut(devLogSerial, PSTR("\"measures\":["));
  doOutputNumberJSON(currentIdx, tFuelEcon, 3, PSTR(",")); // current fuel economy
  doOutputNumberJSON(tankIdx, tFuelEcon, 3, PSTR("],\n")); // tank fuel economy

  text::stringOut(devLogSerial, PSTR("\"markers\":["));
  doOutputNumberJSON(
    min(
      999000,   //do not let scale exceed 999
      doCalculate(instantIdx, tFuelEcon))
//    instantIdx, tFuelEcon
    , 3
    , PSTR("]")); // instantaneous fuel economy
//  doOutputNumberJSON(5 * fuelEconomyFIRvalue / 3, 3, PSTR("]\xfd")); // 5/3 averaged instantaneous fuel economy over time
//   text::stringOut(devLogSerial, PSTR("\}]\r")); // end JSON payload, and go trigger read on python.script
  text::stringOut(devLogSerial, PSTR("\}]\n")); // end JSON payload, and go trigger read on python.script
  text::stringOut(devLogSerial, PSTR("\r")); 
}  //end sendJson function
Attached Files
File Type: zip last_known_good_json_method.c.zip (3.7 KB, 27 views)
  Reply With Quote
The Following 2 Users Say Thank You to skybolt For This Useful Post:
josemapiro (06-17-2017), t vago (10-15-2017)