public void parseAndUpdate(String request, String payLoad, String result) {

    JsonParser parser = new JsonParser();
    JsonObject jsonObject = null;

    try {
      if (request != null && result != null && result != "null") {
        // first, update state objects
        switch (request) {
          case TESLA_DRIVE_STATE:
            {
              driveState = gson.fromJson(result, DriveState.class);
              break;
            }
          case TESLA_GUI_STATE:
            {
              guiState = gson.fromJson(result, GUIState.class);
              break;
            }
          case TESLA_VEHICLE_STATE:
            {
              vehicleState = gson.fromJson(result, VehicleState.class);
              break;
            }
          case TESLA_CHARGE_STATE:
            {
              chargeState = gson.fromJson(result, ChargeState.class);
              if (chargeState.charging_state != null
                  && chargeState.charging_state.equals("Charging")) {
                updateState(CHANNEL_CHARGE, OnOffType.ON);
              } else {
                updateState(CHANNEL_CHARGE, OnOffType.OFF);
              }

              break;
            }
          case TESLA_CLIMATE_STATE:
            {
              climateState = gson.fromJson(result, ClimateState.class);
              break;
            }
        }

        // secondly, reformat the response string to a JSON compliant
        // object for some specific non-JSON compatible requests
        switch (request) {
          case TESLA_MOBILE_ENABLED_STATE:
            {
              jsonObject = new JsonObject();
              jsonObject.addProperty(TESLA_MOBILE_ENABLED_STATE, result);
              break;
            }
          default:
            {
              jsonObject = parser.parse(result).getAsJsonObject();
              break;
            }
        }
      }

      // process the result
      if (jsonObject != null && result != null && !result.equals("null")) {
        // deal with responses for "set" commands, which get confirmed
        // positively, or negatively, in which case a reason for failure
        // is provided
        if (jsonObject.get("reason") != null && jsonObject.get("reason").getAsString() != null) {
          boolean requestResult = jsonObject.get("result").getAsBoolean();
          logger.debug(
              "The request ({}) execution was {}, and reported '{}'",
              new Object[] {
                request,
                requestResult ? "successful" : "not successful",
                jsonObject.get("reason").getAsString()
              });
        } else {
          Set<Map.Entry<String, JsonElement>> entrySet = jsonObject.entrySet();
          for (Map.Entry<String, JsonElement> entry : entrySet) {
            try {
              TeslaChannelSelector selector =
                  TeslaChannelSelector.getValueSelectorFromRESTID(entry.getKey());
              if (!selector.isProperty()) {
                if (!entry.getValue().isJsonNull()) {
                  updateState(
                      selector.getChannelID(),
                      teslaChannelSelectorProxy.getState(
                          entry.getValue().getAsString(), selector, editProperties()));
                } else {
                  updateState(selector.getChannelID(), UnDefType.UNDEF);
                }
              } else {
                if (!entry.getValue().isJsonNull()) {
                  Map<String, String> properties = editProperties();
                  properties.put(selector.getChannelID(), entry.getValue().getAsString());
                  updateProperties(properties);
                }
              }
            } catch (Exception e) {
              logger.debug(
                  "Unable to handle the variable/value pair '{}':'{}'",
                  entry.getKey(),
                  entry.getValue());
            }
          }
        }
      }
    } catch (Exception p) {
      logger.error(
          "An exception occurred while parsing data received from the vehicle: '{}'",
          p.getMessage());
    }
  }
        @Override
        public void run() {
          try {
            if (isAwake()) {
              if (!isEstablished
                  || (!isInMotion()
                      && (System.currentTimeMillis() - lastEventSystemTime
                          > EVENT_RETRY_INTERVAL))) {

                if (!establishEventStream()) {
                  if ((System.currentTimeMillis() - lastEventSystemTime
                      > EVENT_RECOVERY_INTERVAL)) {
                    logger.warn("Event Stream : Resetting the vehicle connection");
                    connect();
                  }
                }
              }

              try {
                if (isEstablished) {
                  String line = null;
                  try {
                    line = eventBufferedReader.readLine();
                  } catch (Exception e) {
                    // we just move on. If we are here, then is most
                    // probably due to Premature EOF exceptions
                  }
                  if (line != null) {
                    lastEventSystemTime = System.currentTimeMillis();
                    logger.debug("Received an event: '{}'", line);
                    String vals[] = line.split(",");
                    if (!vals[0].equals(lastEventTimeStamp)) {
                      lastEventTimeStamp = vals[0];
                      for (int i = 0; i < EventKeys.values().length; i++) {
                        try {
                          TeslaChannelSelector selector =
                              TeslaChannelSelector.getValueSelectorFromRESTID(
                                  (EventKeys.values()[i]).toString());
                          if (!selector.isProperty()) {
                            State newState =
                                teslaChannelSelectorProxy.getState(
                                    vals[i], selector, editProperties());
                            if (newState != null && !vals[i].equals("")) {
                              updateState(selector.getChannelID(), newState);
                            } else {
                              updateState(selector.getChannelID(), UnDefType.UNDEF);
                            }
                          } else {
                            Map<String, String> properties = editProperties();
                            properties.put(
                                selector.getChannelID(), (selector.getState(vals[i])).toString());
                            updateProperties(properties);
                          }
                        } catch (Exception e) {
                          logger.warn(
                              "An exception occurred while processing an event received from the vehicle; '{}'",
                              e.getMessage());
                        }
                      }
                    }
                  }
                }
              } catch (Exception e) {
                logger.error(
                    "An exception occurred while reading event inputs from vehicle '{}' : {}",
                    vehicle.vin,
                    e.getMessage());
                isEstablished = false;
              }
            } else {
              logger.debug("Event stream : The vehicle is not awake");
              if (vehicle != null) {
                // wake up the vehicle until streaming token <> 0
                logger.debug("Event stream : Wake up vehicle");
                sendCommand(TESLA_COMMAND_WAKE_UP);
              } else {
                logger.debug("Event stream : Querying the vehicle");
                vehicle = queryVehicle();
              }
            }
          } catch (Exception t) {
            logger.error("An exception ocurred in the event stream thread: '{}'", t.getMessage());
          }
        }
  @Override
  public void handleCommand(ChannelUID channelUID, Command command) {

    String channelID = channelUID.getId();
    TeslaChannelSelector selector = TeslaChannelSelector.getValueSelectorFromChannelID(channelID);

    if (selector != null) {
      try {
        switch (selector) {
          case CHARGE_LIMIT_SOC:
            {
              if (command instanceof PercentType) {
                setChargeLimit(((PercentType) command).intValue());
              } else if (command instanceof OnOffType && command == OnOffType.ON) {
                setChargeLimit(100);
              } else if (command instanceof OnOffType && command == OnOffType.OFF) {
                setChargeLimit(0);
              } else if (command instanceof IncreaseDecreaseType
                  && command == IncreaseDecreaseType.INCREASE) {
                setChargeLimit(Math.min(chargeState.charge_limit_soc + 1, 100));
              } else if (command instanceof IncreaseDecreaseType
                  && command == IncreaseDecreaseType.DECREASE) {
                setChargeLimit(Math.max(chargeState.charge_limit_soc - 1, 0));
              }
              break;
            }
          case TEMPERATURE:
            {
              if (command instanceof DecimalType) {
                setTemperature(((DecimalType) command).floatValue());
              }
              break;
            }
          case SUN_ROOF_STATE:
            {
              if (command instanceof StringType) {
                setSunroof(command.toString());
              }
              break;
            }
          case SUN_ROOF:
            {
              if (command instanceof PercentType) {
                moveSunroof(((PercentType) command).intValue());
              } else if (command instanceof OnOffType && command == OnOffType.ON) {
                moveSunroof(100);
              } else if (command instanceof OnOffType && command == OnOffType.OFF) {
                moveSunroof(0);
              } else if (command instanceof IncreaseDecreaseType
                  && command == IncreaseDecreaseType.INCREASE) {
                moveSunroof(Math.min(chargeState.charge_limit_soc + 1, 100));
              } else if (command instanceof IncreaseDecreaseType
                  && command == IncreaseDecreaseType.DECREASE) {
                moveSunroof(Math.max(chargeState.charge_limit_soc - 1, 0));
              }
              break;
            }
          case CHARGE_TO_MAX:
            {
              if (command instanceof OnOffType) {
                if (((OnOffType) command) == OnOffType.ON) {
                  setMaxRangeCharging(true);
                } else {
                  setMaxRangeCharging(false);
                }
              }
              break;
            }
          case CHARGE:
            {
              if (command instanceof OnOffType) {
                if (((OnOffType) command) == OnOffType.ON) {
                  charge(true);
                } else {
                  charge(false);
                }
              }
              break;
            }
          case FLASH:
            {
              if (command instanceof OnOffType) {
                if (((OnOffType) command) == OnOffType.ON) {
                  flashLights();
                }
              }
              break;
            }
          case HONK_HORN:
            {
              if (command instanceof OnOffType) {
                if (((OnOffType) command) == OnOffType.ON) {
                  honkHorn();
                }
              }
              break;
            }
          case CHARGEPORT:
            {
              if (command instanceof OnOffType) {
                if (((OnOffType) command) == OnOffType.ON) {
                  openChargePort();
                }
              }
              break;
            }
          case DOOR_LOCK:
            {
              if (command instanceof OnOffType) {
                if (((OnOffType) command) == OnOffType.ON) {
                  lockDoors(true);
                } else {
                  lockDoors(false);
                }
              }
              break;
            }
          case AUTO_COND:
            {
              if (command instanceof OnOffType) {
                if (((OnOffType) command) == OnOffType.ON) {
                  autoConditioning(true);
                } else {
                  autoConditioning(false);
                }
              }
              break;
            }
          default:
            break;
        }
        return;
      } catch (IllegalArgumentException e) {
        logger.warn(
            "An error occurred while trying to set the read-only variable associated with channel '{}' to '{}'",
            channelID,
            command.toString());
      }
    }
  }