robinostlund / volkswagencarnet

A python library for volkswagen carnet
GNU General Public License v3.0
66 stars 37 forks source link

ModuleNotFoundError: No module named 'volkswagencarnet' #124

Closed odelma closed 2 years ago

odelma commented 3 years ago

I noted this is same as issue #10 but for me the cause is something different. My environmnet is Raspberry Pi 3B+ with 3.7.3. I have installed several modules with pip and have not encountered any issues. But now, after installing volkswagencarnet and testing provided example script I just get an import error for volkswagencarnet: Traceback (most recent call last): File "/home/pi/scripts/carnet_test.py", line 7, in <module> import volkswagencarnet ModuleNotFoundError: No module named 'volkswagencarnet'

pip show lists volkswagencarnet 4.4.34

Sorry for this very basic question, but for me this is very puzzling πŸ˜„ Any help is very much appreciated.

JohNan commented 3 years ago

I have not updated the examples or any sample code since migrating to the new api. That's probably the reason for your errors.

odelma commented 3 years ago

Thanks, I see. Was a bit hasty πŸ˜„ I got it working now by looking at the dummy test in test and I am able to print out basic info. This is already very nice.

I tried to use setLock but was not able to get that working (was not able to get past "TypeError: setLock() missing 1 required positional argument: 'spin'" although it is actually the "self" that is missing). Would it be possible to get an example how to use locking/unlocking through this library? Thanks a lot, great work.

azinman commented 3 years ago

It actually seems to me that it installs directly into my site-packages folder, but not in a volkswagencarnet subfolder. The files like vw_connection.py are just in site-packages. Something is wrong with the setup that's not modularizing it.

eibalinchen commented 3 years ago

Thanks, I see. Was a bit hasty πŸ˜„ I got it working now by looking at the dummy test in test and I am able to print out basic info. This is already very nice.

I tried to use setLock but was not able to get that working (was not able to get past "TypeError: setLock() missing 1 required positional argument: 'spin'" although it is actually the "self" that is missing). Would it be possible to get an example how to use locking/unlocking through this library? Thanks a lot, great work.

Hi odelma, can you please post your script that you used to make it work? Greetings, AndrΓ©

odelma commented 3 years ago

Sure, I'm just running this now:

#!/usr/bin/python3
"""Communicate with We Connect services."""
import base64
import os

"""Modified to utilize API calls derived from Android Apps instead of Web API"""
import re
import time
import logging
import asyncio
import hashlib
import jwt

from sys import version_info, argv
from datetime import timedelta, datetime
from urllib.parse import urljoin, parse_qs, urlparse
from json import dumps as to_json
import aiohttp
from bs4 import BeautifulSoup
from base64 import b64encode
from vw_utilities import read_config, json_loads
from vw_vehicle import Vehicle

from aiohttp import ClientSession, ClientTimeout
from aiohttp.hdrs import METH_GET, METH_POST

from vw_const import (
    BRAND,
    COUNTRY,
    HEADERS_SESSION,
    HEADERS_AUTH,
    BASE_SESSION,
    BASE_AUTH,
    CLIENT,
    XCLIENT_ID,
    XAPPVERSION,
    XAPPNAME,
    USER_AGENT,
    APP_URI,
)

import vw_connection

async def main():
    """Main method."""
    if '-v' in argv:
        logging.basicConfig(level=logging.INFO)
    elif '-vv' in argv:
        logging.basicConfig(level=logging.DEBUG)
    else:
        logging.basicConfig(level=logging.ERROR)

    async with ClientSession() as session:
        connection = vw_connection.Connection(session, 'my@mail.com', 'mypassword')
        if await connection.doLogin():
            if await connection.update():
                for vehicle in connection.vehicles:
                    print(f'Vehicle id: {vehicle}')
                    print('Supported sensors:')
                    for instrument in vehicle.dashboard().instruments:
                        print(f' - {instrument.name} (domain:{instrument.component}) - {instrument.str_state}')

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

Just put you crendentials to the connection part.

eibalinchen commented 3 years ago

Sure, I'm just running this now:

#!/usr/bin/python3
"""Communicate with We Connect services."""
import base64
import os

"""Modified to utilize API calls derived from Android Apps instead of Web API"""
import re
import time
import logging
import asyncio
import hashlib
import jwt

from sys import version_info, argv
from datetime import timedelta, datetime
from urllib.parse import urljoin, parse_qs, urlparse
from json import dumps as to_json
import aiohttp
from bs4 import BeautifulSoup
from base64 import b64encode
from vw_utilities import read_config, json_loads
from vw_vehicle import Vehicle

from aiohttp import ClientSession, ClientTimeout
from aiohttp.hdrs import METH_GET, METH_POST

from vw_const import (
    BRAND,
    COUNTRY,
    HEADERS_SESSION,
    HEADERS_AUTH,
    BASE_SESSION,
    BASE_AUTH,
    CLIENT,
    XCLIENT_ID,
    XAPPVERSION,
    XAPPNAME,
    USER_AGENT,
    APP_URI,
)

import vw_connection

async def main():
    """Main method."""
    if '-v' in argv:
        logging.basicConfig(level=logging.INFO)
    elif '-vv' in argv:
        logging.basicConfig(level=logging.DEBUG)
    else:
        logging.basicConfig(level=logging.ERROR)

    async with ClientSession() as session:
        connection = vw_connection.Connection(session, 'my@mail.com', 'mypassword')
        if await connection.doLogin():
            if await connection.update():
                for vehicle in connection.vehicles:
                    print(f'Vehicle id: {vehicle}')
                    print('Supported sensors:')
                    for instrument in vehicle.dashboard().instruments:
                        print(f' - {instrument.name} (domain:{instrument.component}) - {instrument.str_state}')

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

Just put you crendentials to the connection part.

great odelma, this provides the information I have been looking for for so long. many thanks!!"

I want to see what I can do to be able to open or close the cart now too.

Greets AndrΓ©

odelma commented 3 years ago

Sounds good πŸ˜ƒ I also tried with the setLock function

async def setLock(self, vin, data, spin):
        """Remote lock and unlock actions."""
        try:
            await self.set_token('vwg')
            # Prepare data, headers and fetch security token
            if 'Content-Type' in self._session_headers:
                contType = self._session_headers['Content-Type']
            else:
                contType = ''
            if 'unlock' in data:
                self._session_headers['X-mbbSecToken'] = await self.get_sec_token(vin=vin, spin=spin, action='unlock')
            else:
                self._session_headers['X-mbbSecToken'] = await self.get_sec_token(vin=vin, spin=spin, action='lock')
            self._session_headers['Content-Type'] = 'application/vnd.vwg.mbb.RemoteLockUnlock_v1_0_0+xml'
            response = await self.dataCall(f'fs-car/bs/rlu/v1/{BRAND}/{self._session_country}/vehicles/$vin/actions', vin, data=data)
            # Clean up headers
            self._session_headers.pop('X-mbbSecToken', None)
            self._session_headers.pop('Content-Type', None)
            if contType: self._session_headers['Content-Type'] = contType
            if not response:
                raise Exception('Invalid or no response')
            elif response == 429:
                return dict({'id': None, 'state': 'Throttled', 'rate_limit_remaining': 0})
            else:
                request_id = response.get('rluActionResponse', {}).get('requestId', 0)
                request_state = response.get('rluActionResponse', {}).get('requestId', 'unknown')
                remaining = response.get('rate_limit_remaining', -1)
                _LOGGER.debug(
                    f'Request for lock action returned with state "{request_state}", request id: {request_id}, remaining requests: {remaining}')
                return dict({'id': str(request_id), 'state': request_state, 'rate_limit_remaining': remaining})
        except:
            self._session_headers.pop('X-mbbSecToken', None)
            self._session_headers.pop('Content-Type', None)
            if contType: self._session_headers['Content-Type'] = contType
            raise
        return False

But had only a short time to test and with my poor python skills couldn't work it out. Let us know if you do... πŸ‘

eibalinchen commented 3 years ago

hi,

my python knowledge is also rudimentary. can you send me the complete script for the setlock function and your added commands?

then i have one more question: are there any restrictions from your point of view regarding the frequency of the queries? Since a few minutes I get error messages after half of the queries and the odometer data is wrong.

odelma commented 3 years ago

Sorry, I don't remember exactly all the option I tried but basically I just added the setLock function from above to the script and then I called it with parameters (if I remember correct). Something like python3 carnet.py setLock "VIN" "Lock" "SPIN" ..and then received this "TypeError: setLock() missing 1 required positional argument: 'spin'"

Langer75 commented 2 years ago

If someone is interested. I coded a small script to use the library via command line volkswagencarnet-client

odelma commented 2 years ago

This is great, thanks! πŸ‘

robinostlund commented 2 years ago

@odelma i think this should be solved in the latest release, but i am to 99% sure that you need to do some modifications on your side to get it working as it where some breaking changes :)