SAIC-iSmart-API / saic-python-mqtt-gateway

A service that queries the data from an MG iSMART account and publishes the data over MQTT and to other sources
MIT License
71 stars 22 forks source link

Potential bug: Car polling conflicts with car scheduled charging #62

Open nanomad opened 1 year ago

nanomad commented 1 year ago

I'm not sure if this is a bug, but if it is it may be worth considering what we can do to avoid it.

In the past couple of weeks I've been noticing that the car starts charging as soon as I connect the plug of my EVSE instead of respecting whatever it is configured in the app.

Example:

Looking at the gateway logs I see:

2023-07-29 16:15:35,248 Updating vehicle status
2023-07-29 16:15:51,556 Updating charging status

(1) Car gets parked and charger is physically connected

2023-07-29 16:16:38,594 Updating vehicle status
2023-07-29 16:16:54,959 Updating charging status

(2) Here the gateway detects the charger being plugged in, but the battery is not yet charging

2023-07-29 16:19:12,480 Updating vehicle status
2023-07-29 16:19:29,475 Updating charging status

(3) Here the gateway detects that the car is charging

I have a feeling that the polling that happened between (1) and (2) was the trigger for the car to start charging

nanomad commented 1 year ago

Confirmed by using the official MG App by another user:

"If I set the scheduled recharge I no longer have to open the App from the phone, if I open the app the car wakes up and the recharge starts I tried several times and it always did this"

This is quite serious and worth discussing @tosate

tosate commented 1 year ago

That means as soon as the gateway detects the scheduled charging, it should not request the status until the charging time window starts?

Polling the messages does not wake-up the car. What about requesting the scheduled charging? Does this information originate from the car or from the server? Probably from the server, right?

So maybe this is how it works. You schedule the charging and the server triggers it by waking up the car.

nanomad commented 1 year ago

Unfortunately it's all car-side. I've done a couple of tests and managed to reproduce it only if:

My bet is that this is either a race condition inside the BMS/OBC (It gets confused about the time?) or it is done on purpose when it notices a low enough level on the 12V volt battery.

I had the second happen by mistake (I had an infinite loop in my code) and the BMS started charging the 12V battery as soon as it got below 12.4V

nanomad commented 1 year ago

Looking at the charts of the past month I'm going to exclude the 12V battery being too low. Looking at what the car does, the refresh of the car state wakes up a lot of systems, while the refresh of the charging state seems to do almost nothing.

Given we can detect if the car is charging just by looking at the current flow (A) I'll test-drive a new version that only refreshes that

tosate commented 1 year ago

That means we try the following:

Would this work?

tosate commented 1 year ago

Okay, my mistake. We don't read the scheduled charging from the server, we learn about it because the user configures it through the MQTT gateway.

nanomad commented 1 year ago

That means we try the following:

  • We query the vehicle state only after receiving a motor start notification
  • As soon as we detect that the engine is not running we query the charging state only

Would this work?

I think so, that should minimize the number of systems that gets woken up when the car is off. Incidentally, the scheduled charging info is provided by the same api call

nanomad commented 1 year ago

We can either use this to detect if the car is charging: charge_status.charging_gun_state and charge_mgmt_data.get_current() < 0

or we can study what chargingType does. Right now:

tosate commented 1 year ago

I could imagine

Do you save the history of the MQTT topics? While MQTT browser is running on my laptop, it saves the history for each topic. But this history is gone after closing the application. Does your MQTT server store the history?

tosate commented 1 year ago

I think this could be done with HA even for values within a JSON value

nanomad commented 1 year ago

I could imagine

  • 0: not charging, not plugged-in
  • 1: not charging, plugged-in
  • 3: driving
  • 6: slow charging
  • 7: fast charging

Do you save the history of the MQTT topics? While MQTT browser is running on my laptop, it saves the history for each topic. But this history is gone after closing the application. Does your MQTT server store the history?

I dump almost everything into influxdb using telegraf:

# INPUT PLUGINS
[[inputs.mqtt_consumer]]
    servers = ["tcp://mqtt-mosquitto:1883"]
    username = "$MQTT_USERNAME"
    password = "$MQTT_PASSWORD"

    persistent_session = true
    client_id = "telegraf-saic"
    qos = 1

    data_format = "csv"
    csv_column_names = ["value"]
    csv_header_row_count = 0

    topics = [
      "saic/+/vehicles/+/#",
      "saic/+/bms/#",

    ]
    topic_tag = ""
    [[inputs.mqtt_consumer.topic_parsing]]
        topic = "saic/+/vehicles/+/+/+"
        measurement = "_/_/_/_/measurement/_"
        tags = "_/_/_/vin/_/field_name"

    [[inputs.mqtt_consumer.topic_parsing]]
        topic = "saic/+/bms/+"
        measurement = "_/_/measurement/_"
        tags = "_/vin/_/field_name"

[[processors.starlark]]
  source = '''
def apply(metric):
  if 'field_name' in metric.tags:
    metric.fields[str(metric.tags['field_name'])] = metric.fields['value']
    metric.fields.pop('value',None)
    metric.tags.pop('field_name', None)
  return metric
'''
tosate commented 1 year ago

It took me the entire day to set this up, but I think it's working now. The configuration above does not store the JSON requests and responses. I think it would not capture the chargingType value.

How do you access or visualize the data? Are you using Grafana? I have just send some queries with postman.

nanomad commented 1 year ago

chargingType is exposed by itself in its own topic, so you should have it (I do).

image

I use the influxdb UI itself, it's pretty basic but it gets the job done for simple analysis like this

tosate commented 1 year ago

I have modified the refresh so that it queries the charging status only during charging. You can find this in the branch no-vehicle-state-while-charging. With this modification, I have also moved ABRP into the MQTT gateway.

I am not sure if requesting the charging status only minimizes the number of systems that get woken up when the car is off. The display still turns on during refresh.

nanomad commented 1 year ago

I have modified the refresh so that it queries the charging status only during charging. You can find this in the branch no-vehicle-state-while-charging. With this modification, I have also moved ABRP into the MQTT gateway.

I am not sure if requesting the charging status only minimizes the number of systems that get woken up when the car is off. The display still turns on during refresh.

I think this causes issues if we start e.g. the A/C while the car is charging. Then the car state won't be refreshed and we won't get any info about the A/C state. The same goes for the internal car temp (if I want to check the interior temp)

tosate commented 1 year ago

Okay, this is why you did not implement this yet ;-) I just wanted to try it out. Maybe I will take over the ABRP part into the 0.4.-rc branch. But this has to wait until my holidays are over.