Toegang krijgen tot de OMNI API

SuperStroom
Runner-up
Runner-up
Berichten: 13
Lid geworden op: 10 mar 2019, 11:09

Ik heb even armpje moeten drukken met nodered om een en ander naar file te loggen. Later doe ik het mooier naar een database of iets dergelijks. Wat me even tijd kostte was het asynchrone gedrag van de promise. Dat kan dus opgelost worden door een node.send(msg) te doen ipv een return msg. De javascript-code van het functieblok is:

Code: Selecteer alles

const Stromer = global.get('stromerApi');

const api = new Stromer({
username: "***",
password: "****",
client_id: "*****",
client_secret: "*****"
});

function processResponse(state) {
  msg['payload'] = state;
  node.send(msg);
}

api.bike.state.get().then(state => processResponse(state));
en om het npm pakket van Tim https://github.com/TimBroddin/stromer-api aan de praat te krijgen moet ./.node-red/setting.js nog aangepast moet worden. Daarin staat de functie functionGlobalContext waaraan de require uit het originele voorbeeld toegevoegd moet worden. Bijvoorbeeld:

Code: Selecteer alles

    functionGlobalContext: {
        // os:require('os'),
        // octalbonescript:require('octalbonescript'),
        // jfive:require("johnny-five"),
        // j5board:require("johnny-five").Board({repl:false})
        stromerApi:require('stromer-api')
    },
Stromer ST3 2019 Cool white - ww 32,5km
Gebruikersavatar
Louis_ST2
Expert
Expert
Netherlands
Berichten: 296
Lid geworden op: 03 sep 2017, 21:28
Locatie: Langeraar

jan2642 schreef: 19 mar 2019, 20:09
Louis_ST2 schreef: 19 mar 2019, 19:18 En hoeveel characters is de Client secret ?
Ja, dat helpt natuurlijk. Er zijn maar 2 strings met de juiste lengte, een macht van 2.
Hoe moeilijk is het om gewoon 128 te zeggen...
Na een ST2 is het nu een zwarte ST2+1 geworden. ww 30 km enkele reis. BF, Winter Contis erop
Gebruikersavatar
Louis_ST2
Expert
Expert
Netherlands
Berichten: 296
Lid geworden op: 03 sep 2017, 21:28
Locatie: Langeraar

SuperStroom schreef: 21 mar 2019, 22:44 Er is een goede kans dat de api url en de gezochte client_id en client_secret dicht bij elkaar staan. Probeer een FindInFiles op "https://api3.stromer-portal.ch/". Nadat alle bovenstaande decompile instructies gevolgd zijn natuurlijk.

Thanks !!
Na een ST2 is het nu een zwarte ST2+1 geworden. ww 30 km enkele reis. BF, Winter Contis erop
NickName
Pro
Pro
Berichten: 32
Lid geworden op: 29 dec 2017, 21:27

hallo forumleden/programmeurs,

is er iemand die een newbie in deze materie verder op weg zou kunnen helpen door wat licht in de tunnel te schijnen?

* ik heb mijn client_id & client_secret (via JADX online decompile van APK)
* ik heb mijn username & password voor Stromer login
* nodejs (v10.15.3), npm (6.4.1) en stromer-api (https://github.com/TimBroddin/stromer-api) zijn geïnstalleerd
* app.js aangemaakt volgens instructie (in een nieuwe, lege map)

Maar helaas verschijnt volgende foutcode en krijg ik geen return van mijn fiets waarop de Omni het 3G-icoon brandt:

"
undefined
beep
(node:24168) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'name' of undefined
"
Alle suggesties welkom!
zumoto
Rookie
Rookie
Netherlands
Berichten: 7
Lid geworden op: 10 mar 2019, 07:45

merstro schreef: 04 okt 2018, 11:05 Ik heb het inmiddels even uitgezocht met een beetje python code:
Ik probeer op een Mac de python code te starten, maar get_access_token levert steeds een "<Response [401]>" op. Is dit een bekend probleem?

Ik haal eerst met get_code de code op (dat duurt lang maar gaat goed) en die geef ik weer door.

Dit is het stukje code dat ik nu heb staan (let op: ik heb de dubbele slash voor de '/o/token' verwijderd):

Code: Selecteer alles

def get_access_token(client_id, client_secret, code):
    url = "https://api3.stromer-portal.ch/o/token/"
    params = {
        "grant_type": "authorization_code",
        "client_id": client_id,
        "client_secret": client_secret,
        "code": code,
        "redirect_uri": "stromerauth://auth",
    }

    res = requests.post(url, params=params)

    print(res)

    return res.json()["access_token"]
jan2642
Pro
Pro
Berichten: 27
Lid geworden op: 26 okt 2018, 21:01
Locatie: Tienen

Dit is een stukje python dat ik momenteel gebruik:

Code: Selecteer alles

#!/usr/bin/env python3

import requests
from urllib.parse import urlencode, parse_qs, splitquery
from datetime import datetime
import json

password = ""
username = ""
client_id = ""
client_secret = ""

def get_code(client_id, username, password):
    url = "https://api3.stromer-portal.ch/users/login/"
    s = requests.session()
    res = s.get(url)
    s.cookies

    qs = urlencode(
        {
            "client_id": client_id,
            "response_type": "code",
            "redirect_url": "stromerauth://auth",
            "scope": "bikeposition bikestatus bikeconfiguration bikelock biketheft bikedata bikepin bikeblink userprofile",
        }
    )

    data = {
        "password": password,
        "username": username,
        "csrfmiddlewaretoken": s.cookies.get("csrftoken"),
        "next": "/o/authorize/?" + qs,
    }

    res = s.post(url, data=data, headers=dict(Referer=url), allow_redirects=False)
    res = s.send(res.next, allow_redirects=False)
    _, qs = splitquery(res.headers["Location"])
    code = parse_qs(qs)["code"][0]
    return code

def get_access_token(client_id, client_secret, code):
    url = "https://api3.stromer-portal.ch//o/token/"
    params = {
        "grant_type": "authorization_code",
        "client_id": client_id,
        "client_secret": client_secret,
        "code": code,
        "redirect_uri": "stromerauth://auth",
    }

    res = requests.post(url, params=params)
    return res.json()["access_token"]


def call_api(access_token, endpoint, params={}):
    url = "https://api3.stromer-portal.ch/rapi/mobile/v2/%s" % endpoint
    headers = {"Authorization": "Bearer %s" % access_token}
    res = requests.get(url, headers=headers, params={})
    data = res.json()["data"]
    if isinstance(data, list):
        return data[0]
    else:
        return data

def call_bike(access_token, bike, endpoint, cached = "true"):
    endpoint = 'bike/%s/%s' % (bike["bikeid"], endpoint)
    params = {'cached':'%s' % cached}
    state = call_api(access_token, endpoint, params)
    return state;

code = get_code(client_id, username, password)
access_token = get_access_token(client_id, client_secret, code)
bike = call_api(access_token, "bike")
print('bike:', json.dumps(bike, indent=True))

state = call_bike(access_token, bike, 'state/')
print('state:', json.dumps(state, indent=True))

position = call_bike(access_token, bike, 'position/')
print('position:', json.dumps(position, indent=True))
Gebruikersavatar
Louis_ST2
Expert
Expert
Netherlands
Berichten: 296
Lid geworden op: 03 sep 2017, 21:28
Locatie: Langeraar

NickName schreef: 29 apr 2019, 21:30
Maar helaas verschijnt volgende foutcode en krijg ik geen return van mijn fiets waarop de Omni het 3G-icoon brandt:

Je communiceert niet met je fiets direct maar met de gegevens bank van Stromer. Je kunt ook de gegevens opvragen, zoals totalen, met je App als de fiets uit staat.
Na een ST2 is het nu een zwarte ST2+1 geworden. ww 30 km enkele reis. BF, Winter Contis erop
Gebruikersavatar
Louis_ST2
Expert
Expert
Netherlands
Berichten: 296
Lid geworden op: 03 sep 2017, 21:28
Locatie: Langeraar

Stromermap.jpg
Stromermap.jpg (41.41 KiB) 7240 keer bekeken
Map met bestanden.

Stromer.bat is het uit te voeren bestand en bevat:

@echo off
node app.js
echo.
echo datum: %date%
echo.
pause



Ik sla de gegevens soms op en weet nog wanneer ik de gegevens geproduceerd heb.
Na een ST2 is het nu een zwarte ST2+1 geworden. ww 30 km enkele reis. BF, Winter Contis erop
zumoto
Rookie
Rookie
Netherlands
Berichten: 7
Lid geworden op: 10 mar 2019, 07:45

Ben nog niet in gelegenheid geweest te testen maar alvast bedankt voor je reactie.
jan2642 schreef: 30 apr 2019, 14:42 Dit is een stukje python dat ik momenteel gebruik:

Code: Selecteer alles

#!/usr/bin/env python3

import requests
from urllib.parse import urlencode, parse_qs, splitquery
from datetime import datetime
import json

password = ""
username = ""
client_id = ""
client_secret = ""

def get_code(client_id, username, password):
    url = "https://api3.stromer-portal.ch/users/login/"
    s = requests.session()
    res = s.get(url)
    s.cookies

    qs = urlencode(
        {
            "client_id": client_id,
            "response_type": "code",
            "redirect_url": "stromerauth://auth",
            "scope": "bikeposition bikestatus bikeconfiguration bikelock biketheft bikedata bikepin bikeblink userprofile",
        }
    )

    data = {
        "password": password,
        "username": username,
        "csrfmiddlewaretoken": s.cookies.get("csrftoken"),
        "next": "/o/authorize/?" + qs,
    }

    res = s.post(url, data=data, headers=dict(Referer=url), allow_redirects=False)
    res = s.send(res.next, allow_redirects=False)
    _, qs = splitquery(res.headers["Location"])
    code = parse_qs(qs)["code"][0]
    return code

def get_access_token(client_id, client_secret, code):
    url = "https://api3.stromer-portal.ch//o/token/"
    params = {
        "grant_type": "authorization_code",
        "client_id": client_id,
        "client_secret": client_secret,
        "code": code,
        "redirect_uri": "stromerauth://auth",
    }

    res = requests.post(url, params=params)
    return res.json()["access_token"]


def call_api(access_token, endpoint, params={}):
    url = "https://api3.stromer-portal.ch/rapi/mobile/v2/%s" % endpoint
    headers = {"Authorization": "Bearer %s" % access_token}
    res = requests.get(url, headers=headers, params={})
    data = res.json()["data"]
    if isinstance(data, list):
        return data[0]
    else:
        return data

def call_bike(access_token, bike, endpoint, cached = "true"):
    endpoint = 'bike/%s/%s' % (bike["bikeid"], endpoint)
    params = {'cached':'%s' % cached}
    state = call_api(access_token, endpoint, params)
    return state;

code = get_code(client_id, username, password)
access_token = get_access_token(client_id, client_secret, code)
bike = call_api(access_token, "bike")
print('bike:', json.dumps(bike, indent=True))

state = call_bike(access_token, bike, 'state/')
print('state:', json.dumps(state, indent=True))

position = call_bike(access_token, bike, 'position/')
print('position:', json.dumps(position, indent=True))
NickName
Pro
Pro
Berichten: 32
Lid geworden op: 29 dec 2017, 21:27

Louis_ST2 schreef: 06 mei 2019, 19:32 Je communiceert niet met je fiets direct maar met de gegevens bank van Stromer. Je kunt ook de gegevens opvragen, zoals totalen, met je App als de fiets uit staat.
Bedankt, het is me inmiddels gelukt na correctie van client_id (was een typo in geslopen).
Plaats reactie