flobz / psa_car_controller

Control psa car with connected_car v4 API.
GNU General Public License v3.0
391 stars 199 forks source link

Corsa-e: Charge control not working #137

Closed sOckhamSter closed 3 years ago

sOckhamSter commented 3 years ago

I'm not sure if this is a bug, or whether it's just because the (Vauxhall) Corsa-e doesn't support these features. I'm unable to get any of the charge control commands to work. The API appears to send them fine, they just don't do anything. so for example, sending the command: http://localhost:5000/charge_now/YOURVIN/0 ... does not stop the charge. Equally, if I set a time for the charge to stop, or set the percentage threshold, the car ignores them and carries on charging regardless.

Do you know if this is just because the car doesn't support this, or could something be up? The MyVauxhall app does not allow me to perform such actions which is why I suspect that the commands are not supposed to do anything.

thommierother commented 3 years ago

I don't think its a problem of the car itself. The corsa has the same technical platform as the PSA models and even the MyPeugeot App has no option to stop charging from remote (I do this from the wallbox). As far as I understand it, the car receives mqtt messages from the API, e.g. for starting the preconditioning. But other options which are already visible in the API are simply not implemented in the official mobile apps yet.

flobz commented 3 years ago

Look at the log. You can retry the command after 30 second, sometime it's needed to reconnect.

sOckhamSter commented 3 years ago

I've enabled debug on server.py to see what's happening. When I send /charge_now/vin/0 to stop the charge, this is what appears in the logs:

2021-05-24 10:56:49,325 :: DEBUG :: vin:VXKUHZKXZLxxxxxxx longitude:None latitude:None date:2021-05-24 10:32:40+00:00 mileage:2052.8 level:46.0 charge_date:2021-05-24 10:32:40+00:00 level_fuel:None moving:None
2021-05-24 10:56:49,328 :: DEBUG :: position already saved
2021-05-24 10:56:49,329 :: DEBUG :: No abrp token provided
2021-05-24 10:56:49,331 :: DEBUG :: level already stored
2021-05-24 10:56:49,332 :: DEBUG :: charging_status:InProgress 
2021-05-24 10:56:49,333 :: ERROR :: Can't get charge hour: PT30M
Traceback (most recent call last):
  File "/psa_car_controller/my_psacc.py", line 344, in __get_charge_hour
    hour_minute = re.findall(reg, hour_str)[0]
IndexError: list index out of range

And, after enabling debug I now get a lot more in the response from the curl request to the url:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
  "http://www.w3.org/TR/html4/loose.dtd">
<html>
  <head>
    <title>TypeError: cannot unpack non-iterable NoneType object // Werkzeug Debugger</title>
    <link rel="stylesheet" href="?__debugger__=yes&amp;cmd=resource&amp;f=style.css"
        type="text/css">
    <!-- We need to make sure this has a favicon so that the debugger does
         not accidentally trigger a request to /favicon.ico which might
         change the application's state. -->
    <link rel="shortcut icon"
        href="?__debugger__=yes&amp;cmd=resource&amp;f=console.png">
    <script src="?__debugger__=yes&amp;cmd=resource&amp;f=debugger.js"></script>
    <script type="text/javascript">
      var TRACEBACK = 140378457153056,
          CONSOLE_MODE = false,
          EVALEX = true,
          EVALEX_TRUSTED = false,
          SECRET = "xxxxxxxx";
    </script>
  </head>
  <body style="background-color: #fff">
    <div class="debugger">
<h1>TypeError</h1>
<div class="detail">
  <p class="errormsg">TypeError: cannot unpack non-iterable NoneType object</p>
</div>
<h2 class="traceback">Traceback <em>(most recent call last)</em></h2>
<div class="traceback">
  <h3></h3>
  <ul><li><div class="frame" id="frame-140378457150848">
  <h4>File <cite class="filename">"/usr/local/lib/python3.9/site-packages/werkzeug/middleware/dispatcher.py"</cite>,
      line <em class="line">78</em>,
      in <code class="function">__call__</code></h4>
  <div class="source library"><pre class="line before"><span class="ws">            </span>app = self.mounts.get(script, self.app)</pre>
<pre class="line before"><span class="ws"></span> </pre>
<pre class="line before"><span class="ws">        </span>original_script_name = environ.get(&quot;SCRIPT_NAME&quot;, &quot;&quot;)</pre>
<pre class="line before"><span class="ws">        </span>environ[&quot;SCRIPT_NAME&quot;] = original_script_name + script</pre>
<pre class="line before"><span class="ws">        </span>environ[&quot;PATH_INFO&quot;] = path_info</pre>
<pre class="line current"><span class="ws">        </span>return app(environ, start_response)</pre></div>
</div>

<li><div class="frame" id="frame-140378457150752">
  <h4>File <cite class="filename">"/usr/local/lib/python3.9/site-packages/flask/app.py"</cite>,
      line <em class="line">2069</em>,
      in <code class="function">__call__</code></h4>
  <div class="source library"><pre class="line before"><span class="ws">    </span>def __call__(self, environ: dict, start_response: t.Callable) -&gt; t.Any:</pre>
<pre class="line before"><span class="ws">        </span>&quot;&quot;&quot;The WSGI server calls the Flask application object as the</pre>
<pre class="line before"><span class="ws">        </span>WSGI application. This calls :meth:`wsgi_app`, which can be</pre>
<pre class="line before"><span class="ws">        </span>wrapped to apply middleware.</pre>
<pre class="line before"><span class="ws">        </span>&quot;&quot;&quot;</pre>
<pre class="line current"><span class="ws">        </span>return self.wsgi_app(environ, start_response)</pre>
<pre class="line after"><span class="ws"></span> </pre>
<pre class="line after"><span class="ws">    </span>def _request_blueprints(self) -&gt; t.Iterable[str]:</pre>
<pre class="line after"><span class="ws">        </span>if _request_ctx_stack.top.request.blueprint is None:</pre>
<pre class="line after"><span class="ws">            </span>return []</pre>
<pre class="line after"><span class="ws">        </span>else:</pre></div>
</div>

<li><div class="frame" id="frame-140378457150560">
  <h4>File <cite class="filename">"/usr/local/lib/python3.9/site-packages/werkzeug/middleware/proxy_fix.py"</cite>,
      line <em class="line">187</em>,
      in <code class="function">__call__</code></h4>
  <div class="source library"><pre class="line before"><span class="ws">            </span>self.x_prefix, environ_get(&quot;HTTP_X_FORWARDED_PREFIX&quot;)</pre>
<pre class="line before"><span class="ws">        </span>)</pre>
<pre class="line before"><span class="ws">        </span>if x_prefix:</pre>
<pre class="line before"><span class="ws">            </span>environ[&quot;SCRIPT_NAME&quot;] = x_prefix</pre>
<pre class="line before"><span class="ws"></span> </pre>
<pre class="line current"><span class="ws">        </span>return self.app(environ, start_response)</pre></div>
</div>

<li><div class="frame" id="frame-140378457152912">
  <h4>File <cite class="filename">"/usr/local/lib/python3.9/site-packages/flask/app.py"</cite>,
      line <em class="line">2054</em>,
      in <code class="function">wsgi_app</code></h4>
  <div class="source library"><pre class="line before"><span class="ws">            </span>try:</pre>
<pre class="line before"><span class="ws">                </span>ctx.push()</pre>
<pre class="line before"><span class="ws">                </span>response = self.full_dispatch_request()</pre>
<pre class="line before"><span class="ws">            </span>except Exception as e:</pre>
<pre class="line before"><span class="ws">                </span>error = e</pre>
<pre class="line current"><span class="ws">                </span>response = self.handle_exception(e)</pre>
<pre class="line after"><span class="ws">            </span>except:  # noqa: B001</pre>
<pre class="line after"><span class="ws">                </span>error = sys.exc_info()[1]</pre>
<pre class="line after"><span class="ws">                </span>raise</pre>
<pre class="line after"><span class="ws">            </span>return response(environ, start_response)</pre>
<pre class="line after"><span class="ws">        </span>finally:</pre></div>
</div>

<li><div class="frame" id="frame-140378457150176">
  <h4>File <cite class="filename">"/usr/local/lib/python3.9/site-packages/flask/app.py"</cite>,
      line <em class="line">2051</em>,
      in <code class="function">wsgi_app</code></h4>
  <div class="source library"><pre class="line before"><span class="ws">        </span>ctx = self.request_context(environ)</pre>
<pre class="line before"><span class="ws">        </span>error: t.Optional[BaseException] = None</pre>
<pre class="line before"><span class="ws">        </span>try:</pre>
<pre class="line before"><span class="ws">            </span>try:</pre>
<pre class="line before"><span class="ws">                </span>ctx.push()</pre>
<pre class="line current"><span class="ws">                </span>response = self.full_dispatch_request()</pre>
<pre class="line after"><span class="ws">            </span>except Exception as e:</pre>
<pre class="line after"><span class="ws">                </span>error = e</pre>
<pre class="line after"><span class="ws">                </span>response = self.handle_exception(e)</pre>
<pre class="line after"><span class="ws">            </span>except:  # noqa: B001</pre>
<pre class="line after"><span class="ws">                </span>error = sys.exc_info()[1]</pre></div>
</div>

<li><div class="frame" id="frame-140378457153008">
  <h4>File <cite class="filename">"/usr/local/lib/python3.9/site-packages/flask/app.py"</cite>,
      line <em class="line">1501</em>,
      in <code class="function">full_dispatch_request</code></h4>
  <div class="source library"><pre class="line before"><span class="ws">            </span>request_started.send(self)</pre>
<pre class="line before"><span class="ws">            </span>rv = self.preprocess_request()</pre>
<pre class="line before"><span class="ws">            </span>if rv is None:</pre>
<pre class="line before"><span class="ws">                </span>rv = self.dispatch_request()</pre>
<pre class="line before"><span class="ws">        </span>except Exception as e:</pre>
<pre class="line current"><span class="ws">            </span>rv = self.handle_user_exception(e)</pre>
<pre class="line after"><span class="ws">        </span>return self.finalize_request(rv)</pre>
<pre class="line after"><span class="ws"></span> </pre>
<pre class="line after"><span class="ws">    </span>def finalize_request(</pre>
<pre class="line after"><span class="ws">        </span>self,</pre>
<pre class="line after"><span class="ws">        </span>rv: t.Union[ResponseReturnValue, HTTPException],</pre></div>
</div>

<li><div class="frame" id="frame-140378457150032">
  <h4>File <cite class="filename">"/usr/local/lib/python3.9/site-packages/flask/app.py"</cite>,
      line <em class="line">1499</em>,
      in <code class="function">full_dispatch_request</code></h4>
  <div class="source library"><pre class="line before"><span class="ws">        </span>self.try_trigger_before_first_request_functions()</pre>
<pre class="line before"><span class="ws">        </span>try:</pre>
<pre class="line before"><span class="ws">            </span>request_started.send(self)</pre>
<pre class="line before"><span class="ws">            </span>rv = self.preprocess_request()</pre>
<pre class="line before"><span class="ws">            </span>if rv is None:</pre>
<pre class="line current"><span class="ws">                </span>rv = self.dispatch_request()</pre>
<pre class="line after"><span class="ws">        </span>except Exception as e:</pre>
<pre class="line after"><span class="ws">            </span>rv = self.handle_user_exception(e)</pre>
<pre class="line after"><span class="ws">        </span>return self.finalize_request(rv)</pre>
<pre class="line after"><span class="ws"></span> </pre>
<pre class="line after"><span class="ws">    </span>def finalize_request(</pre></div>
</div>

<li><div class="frame" id="frame-140378457152960">
  <h4>File <cite class="filename">"/usr/local/lib/python3.9/site-packages/flask/app.py"</cite>,
      line <em class="line">1485</em>,
      in <code class="function">dispatch_request</code></h4>
  <div class="source library"><pre class="line before"><span class="ws">            </span>getattr(rule, &quot;provide_automatic_options&quot;, False)</pre>
<pre class="line before"><span class="ws">            </span>and req.method == &quot;OPTIONS&quot;</pre>
<pre class="line before"><span class="ws">        </span>):</pre>
<pre class="line before"><span class="ws">            </span>return self.make_default_options_response()</pre>
<pre class="line before"><span class="ws">        </span># otherwise dispatch to the handler for that endpoint</pre>
<pre class="line current"><span class="ws">        </span>return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)</pre>
<pre class="line after"><span class="ws"></span> </pre>
<pre class="line after"><span class="ws">    </span>def full_dispatch_request(self) -&gt; Response:</pre>
<pre class="line after"><span class="ws">        </span>&quot;&quot;&quot;Dispatches the request and on top of that performs request</pre>
<pre class="line after"><span class="ws">        </span>pre and postprocessing as well as HTTP exception catching and</pre>
<pre class="line after"><span class="ws">        </span>error handling.</pre></div>
</div>

<li><div class="frame" id="frame-140378457153344">
  <h4>File <cite class="filename">"/psa_car_controller/web/views.py"</cite>,
      line <em class="line">139</em>,
      in <code class="function">charge_now</code></h4>
  <div class="source "><pre class="line before"><span class="ws">    </span>return jsonify(STYLE_CACHE)</pre>
<pre class="line before"><span class="ws"></span> </pre>
<pre class="line before"><span class="ws"></span> </pre>
<pre class="line before"><span class="ws"></span>@app.route(&#x27;/charge_now/&lt;string:vin&gt;/&lt;int:charge&gt;&#x27;)</pre>
<pre class="line before"><span class="ws"></span>def charge_now(vin, charge):</pre>
<pre class="line current"><span class="ws">    </span>return jsonify(myp.charge_now(vin, charge != 0))</pre>
<pre class="line after"><span class="ws"></span> </pre>
<pre class="line after"><span class="ws"></span> </pre>
<pre class="line after"><span class="ws"></span>@app.route(&#x27;/charge_hour&#x27;)</pre>
<pre class="line after"><span class="ws"></span>def change_charge_hour():</pre>
<pre class="line after"><span class="ws">    </span>return jsonify(myp.change_charge_hour(request.form[&#x27;vin&#x27;], request.form[&#x27;hour&#x27;], request.form[&#x27;minute&#x27;]))</pre></div>
</div>

<li><div class="frame" id="frame-140378457153248">
  <h4>File <cite class="filename">"/psa_car_controller/my_psacc.py"</cite>,
      line <em class="line">374</em>,
      in <code class="function">charge_now</code></h4>
  <div class="source "><pre class="line before"><span class="ws">    </span>def charge_now(self, vin, now):</pre>
<pre class="line before"><span class="ws">        </span>if now:</pre>
<pre class="line before"><span class="ws">            </span>charge_type = &quot;immediate&quot;</pre>
<pre class="line before"><span class="ws">        </span>else:</pre>
<pre class="line before"><span class="ws">            </span>charge_type = &quot;delayed&quot;</pre>
<pre class="line current"><span class="ws">        </span>hour, minute = self.__get_charge_hour(vin)</pre>
<pre class="line after"><span class="ws">        </span>self.__veh_charge_request(vin, hour, minute, charge_type)</pre>
<pre class="line after"><span class="ws">        </span>return True</pre>
<pre class="line after"><span class="ws"></span> </pre>
<pre class="line after"><span class="ws">    </span>def horn(self, vin, count):</pre>
<pre class="line after"><span class="ws">        </span>msg = self.mqtt_request(vin, {&quot;nb_horn&quot;: count, &quot;action&quot;: &quot;activate&quot;})</pre></div>
</div>
</ul>
  <blockquote>TypeError: cannot unpack non-iterable NoneType object</blockquote>
</div>

<div class="plain">
    <p>
      This is the Copy/Paste friendly version of the traceback.
    </p>
    <textarea cols="50" rows="10" name="code" readonly>Traceback (most recent call last):
  File &quot;/usr/local/lib/python3.9/site-packages/werkzeug/middleware/dispatcher.py&quot;, line 78, in __call__
    return app(environ, start_response)
  File &quot;/usr/local/lib/python3.9/site-packages/flask/app.py&quot;, line 2069, in __call__
    return self.wsgi_app(environ, start_response)
  File &quot;/usr/local/lib/python3.9/site-packages/werkzeug/middleware/proxy_fix.py&quot;, line 187, in __call__
    return self.app(environ, start_response)
  File &quot;/usr/local/lib/python3.9/site-packages/flask/app.py&quot;, line 2054, in wsgi_app
    response = self.handle_exception(e)
  File &quot;/usr/local/lib/python3.9/site-packages/flask/app.py&quot;, line 2051, in wsgi_app
    response = self.full_dispatch_request()
  File &quot;/usr/local/lib/python3.9/site-packages/flask/app.py&quot;, line 1501, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File &quot;/usr/local/lib/python3.9/site-packages/flask/app.py&quot;, line 1499, in full_dispatch_request
    rv = self.dispatch_request()
  File &quot;/usr/local/lib/python3.9/site-packages/flask/app.py&quot;, line 1485, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File &quot;/psa_car_controller/web/views.py&quot;, line 139, in charge_now
    return jsonify(myp.charge_now(vin, charge != 0))
  File &quot;/psa_car_controller/my_psacc.py&quot;, line 374, in charge_now
    hour, minute = self.__get_charge_hour(vin)
TypeError: cannot unpack non-iterable NoneType object</textarea>
</div>
<div class="explanation">
  The debugger caught an exception in your WSGI application.  You can now
  look at the traceback which led to the error.  <span class="nojavascript">
  If you enable JavaScript you can also use additional features such as code
  execution (if the evalex feature is enabled), automatic pasting of the
  exceptions and much more.</span>
</div>
      <div class="footer">
        Brought to you by <strong class="arthur">DON'T PANIC</strong>, your
        friendly Werkzeug powered traceback interpreter.
      </div>
    </div>

    <div class="pin-prompt">
      <div class="inner">
        <h3>Console Locked</h3>
        <p>
          The console is locked and needs to be unlocked by entering the PIN.
          You can find the PIN printed out on the standard output of your
          shell that runs the server.
        <form>
          <p>PIN:
            <input type=text name=pin size=14>
            <input type=submit name=btn value="Confirm Pin">
        </form>
      </div>
    </div>
  </body>
</html>

<!--

Traceback (most recent call last):
  File "/usr/local/lib/python3.9/site-packages/werkzeug/middleware/dispatcher.py", line 78, in __call__
    return app(environ, start_response)
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2069, in __call__
    return self.wsgi_app(environ, start_response)
  File "/usr/local/lib/python3.9/site-packages/werkzeug/middleware/proxy_fix.py", line 187, in __call__
    return self.app(environ, start_response)
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2054, in wsgi_app
    response = self.handle_exception(e)
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 2051, in wsgi_app
    response = self.full_dispatch_request()
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1501, in full_dispatch_request
    rv = self.handle_user_exception(e)
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1499, in full_dispatch_request
    rv = self.dispatch_request()
  File "/usr/local/lib/python3.9/site-packages/flask/app.py", line 1485, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**req.view_args)
  File "/psa_car_controller/web/views.py", line 139, in charge_now
    return jsonify(myp.charge_now(vin, charge != 0))
  File "/psa_car_controller/my_psacc.py", line 374, in charge_now
    hour, minute = self.__get_charge_hour(vin)
TypeError: cannot unpack non-iterable NoneType object

-->
sOckhamSter commented 3 years ago

I've just noticed that in 2.3.2 you updated the code to understand PT times, but I can't see that it understands "PT30M", which is currently my default scheduled start time of 00:30. Could it be because of that reason it's crashing for me do you think?

Edit: Ok, so there is a bug in the code in understanding PT30M because if I change my scheduled start time in the app to 10:30 for example, I can now send the stop charge command with no errors. I get a 'true' value returned. But... it does nothing. The logs don't show any issues either that I can see. This is what the logs show when I try to stop the charge. Nothing happens to the car at all, it carries on charging:

2021-05-24 11:40:51,831 :: DEBUG :: vin:VXKUHZKXZLxxxxxx longitude:None latitude:None date:2021-05-24 11:35:11+00:0
0 mileage:2052.8 level:61.0 charge_date:2021-05-24 11:35:11+00:00 level_fuel:None moving:None                       
2021-05-24 11:40:51,834 :: DEBUG :: position already saved                                                          
2021-05-24 11:40:51,836 :: DEBUG :: No abrp token provided                                                          
2021-05-24 11:40:51,837 :: DEBUG :: level already stored                                                            
2021-05-24 11:40:51,838 :: DEBUG :: charging_status:InProgress                                                      
2021-05-24 11:40:52,123 :: INFO :: save config change                                                               
2021-05-24 11:40:52,124 :: INFO :: {"access_token": "051d58e3-a51e-4ef0-855f-xxxxxxxx", "customer_id": "VX-ACNT2
0000xxxxxxx", "correlation_id": "xxxxxxx", "req_date": "2021-05-24T11:40:5
2Z", "vin": "VXKUHZKXZLxxxxxx", "req_parameters": {"program": {"hour": 10, "minute": "30"}, "type": "delayed"}}    
172.17.0.1 - - [24/May/2021 11:40:52] "GET /charge_now/VXKUHZKXZLxxxxxx/0 HTTP/1.1" 200 -                          
2021-05-24 11:40:52,145 :: WARNING :: Disconnected with result code 1                                               
2021-05-24 11:40:52,406 :: INFO :: save config change                                                               
2021-05-24 11:40:52,739 :: DEBUG :: refresh_remote_token: {'scope': 'psaCustomerId psaMqttService', 'expires_in': 89
9, 'token_type': 'Bearer', 'access_token': '30de15e6-8271-407d-baf4-xxxxxxx', 'refresh_token': 'd69ac02c-f443-4
e8d-98f9-xxxxxx'}                                                                                             
2021-05-24 11:40:53,950 :: DEBUG :: vin:VXKUHZKXZLxxxxxx longitude:None latitude:None date:2021-05-24 11:35:11+00:0
0 mileage:2052.8 level:61.0 charge_date:2021-05-24 11:35:11+00:00 level_fuel:None moving:None                       
2021-05-24 11:40:53,953 :: DEBUG :: position already saved                                                          
2021-05-24 11:40:53,954 :: DEBUG :: No abrp token provided                                                          
2021-05-24 11:40:53,956 :: DEBUG :: level already stored                                                            
2021-05-24 11:40:53,957 :: DEBUG :: charging_status:InProgress                                                      
192.168.1.10 - - [24/May/2021 11:40:53] "GET /get_vehicleinfo/VXKUHZKXZLxxxxxx HTTP/1.1" 200 -                     
2021-05-24 11:40:53,964 :: INFO :: <Request 'http://192.168.1.10:8180/charge_control?vin=VXKUHZKXZLxxxxxx&%3Falways
_check=true' [GET]>                                                                                                 
192.168.1.10 - - [24/May/2021 11:40:53] "GET /charge_control?vin=VXKUHZKXZLxxxxxx&?always_check=true HTTP/1.1" 200 
-                                                                                                                   
2021-05-24 11:40:54,007 :: INFO :: Connected with result code {'session present': 0}                                
2021-05-24 11:40:54,008 :: INFO :: subscribe to psa/RemoteServices/to/cid/VX-ACNT20000xxxxxxx/#                     
2021-05-24 11:40:54,009 :: INFO :: subscribe to psa/RemoteServices/events/MPHRTServices/VXKUHZKXZLxxxxxx 
flobz commented 3 years ago

fixed with 0a8c1eab4292ed89da8e707088e86fbfac249635 You have an error: 172.17.0.1 - - [24/May/2021 11:40:52] "GET /charge_now/VXKUHZKXZLxxxxxx/0 HTTP/1.1" 200 -
2021-05-24 11:40:52,145 :: WARNING :: Disconnected with result code 1

sOckhamSter commented 3 years ago

Thanks @flobz any ideas if I can dig into any diagnostics anywhere to get more information on what that error is or what result code 1 means?

flobz commented 3 years ago

It happen when the token expire. What happens when you send the command twice?

sOckhamSter commented 3 years ago

The same thing. I've sent it multiple times with gaps of at least 30 seconds in between, trying different scenarios (i.e. stopping an existing charge, starting a new charge, starting while waiting on a deferred charge, setting a scheduled charge start time, etc). Very odd. Perhaps I need to play around more and collect data... it's just annoying when the family keeps using the car and I can't test all the time!

flobz commented 3 years ago

Does it works to stop the charge from android app ?

sOckhamSter commented 3 years ago

There is no such functionality provided by the MyVauxhall app which was part of my original question - I didn't know if functionality which is not provided by the app itself would work. Using the MyVauxhall app, all I can do is:

flobz commented 3 years ago

when you stop the charge in psa_car_controller, it does a Schedule a deferred charge start time

sOckhamSter commented 3 years ago

Ok, so does that mean when you start the charge, it sets the deferred charge start time to 'now'? Using the app itself works fine to set deferred charge times, and the car is happy to obey. It just doesn't seem to work in psa_car_controller for me :(

flobz commented 3 years ago

it sets the deferred charge start time to 'now'? No it just stop the charge or delay to next day.

Could you try to remove otp.bin ?

sOckhamSter commented 3 years ago

Tried that, ran through the SMS/PIN routine, and the same thing happens.

sOckhamSter commented 3 years ago

Right then, sorry it's taken a while but I've had to play around to test several scenarios. I think I sort of have it working now but it's very fiddly. Until I'd connected the charger to the car and put it into deferred charging mode using the app itself, the charge stop/start wouldn't work. It now works, most of the time.

But, in order to get that far I had to first confirm that setting a deferred charge time via the app worked. After looking at your code I noticed that the /charge_hour API command requires form submission which is difficult to do using a URL call. I tweaked my version as follows:

#@app.route('/charge_hour')
#def change_charge_hour():
#    return jsonify(myp.change_charge_hour(request.form['vin'], request.form['hour'], request.form['minute']))

@app.route('/charge_hour/<string:vin>/<int:hour>/<int:minute>')
def change_charge_hour(vin, hour, minute):
    return jsonify(myp.change_charge_hour(vin, hour, minute))

It might be worth amending views.py to allow a call to change_charge_hour using a single non-form standard URL call do you think? That would make it easy to call using a Home Assistant switch.

flobz commented 3 years ago

Look at the domoticz exemple, it's quite simple to use.

sOckhamSter commented 3 years ago

I think I’m missing something- the examples only show how to use charge_control (to set a stop time), not charge_hour to set a start time?

flobz commented 3 years ago

you just have to do a request like this: http://127.0.0.1:5000/charge_hour?vin=xxx&hour=22&min=0