|
/* |
|
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED |
|
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
|
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
|
CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
|
DEALINGS IN THE SOFTWARE. |
|
*/ |
|
|
|
const axios = require('axios'); |
|
|
|
const getCert = (async (email, password) => { |
|
const ed = await import("@noble/ed25519"); |
|
|
|
const privKey = ed.utils.randomPrivateKey(); // Secure random private key |
|
const pubKey = await ed.getPublicKeyAsync(privKey); |
|
|
|
console.log("Privkey = " + Buffer.from(privKey).toString('base64')); |
|
console.log("Pubkey = " + Buffer.from(pubKey).toString('base64')); |
|
|
|
console.log(""); |
|
|
|
try { |
|
const authResponse = await axios.post('https://my.vanmoof.com/api/v8/authenticate', null, { |
|
headers: { |
|
'Authorization': "Basic "+Buffer.from(email+':'+password).toString('base64'), |
|
'Api-Key': "fcb38d47-f14b-30cf-843b-26283f6a5819", |
|
'User-Agent': "VanMoof/20 CFNetwork/1404.0.5 Darwin/22.3.0", |
|
} |
|
}); |
|
|
|
const authToken = authResponse.data.token; |
|
|
|
const appTokenResponse = await axios.get('https://api.vanmoof-api.com/v8/getApplicationToken', { |
|
headers: { |
|
'Authorization': "Bearer "+authToken, |
|
'Api-Key': "fcb38d47-f14b-30cf-843b-26283f6a5819", |
|
'User-Agent': "VanMoof/20 CFNetwork/1404.0.5 Darwin/22.3.0", |
|
} |
|
}); |
|
|
|
const appToken = appTokenResponse.data.token; |
|
|
|
const bikeDataResponse = await axios.get('https://my.vanmoof.com/api/v8/getCustomerData?includeBikeDetails', { |
|
headers: { |
|
'Authorization': "Bearer "+authToken, |
|
'Api-Key': "fcb38d47-f14b-30cf-843b-26283f6a5819", |
|
'User-Agent': "VanMoof/20 CFNetwork/1404.0.5 Darwin/22.3.0", |
|
} |
|
}); |
|
|
|
for (const bikeIdx in bikeDataResponse.data.data.bikes) { |
|
const bike = bikeDataResponse.data.data.bikes[bikeIdx]; |
|
|
|
console.log("Bike "+bike.name); |
|
console.log("Bike ID: "+ bike.bikeId); |
|
console.log("Frame number: "+ bike.frameNumber); |
|
console.log("Frame serial: "+ bike.frameSerial); |
|
|
|
if (bike.bleProfile === 'ELECTRIFIED_2022') { |
|
console.log("Bike is an SA5"); |
|
console.log("ECU Serial: "+ bike.mainEcuSerial); |
|
|
|
const certificateResponse = await axios.post('https://bikeapi.production.vanmoof.cloud/bikes/'+bike.bikeId+'/create_certificate', { |
|
'public_key': Buffer.from(pubKey).toString('base64'), |
|
}, { |
|
headers: { |
|
'Authorization': "Bearer "+appToken, |
|
'User-Agent': "VanMoof/20 CFNetwork/1404.0.5 Darwin/22.3.0", |
|
} |
|
}); |
|
|
|
console.log("Certificate below:") |
|
console.log("-----------"); |
|
console.log(certificateResponse.data); |
|
console.log("-----------"); |
|
} else { |
|
console.log("Not an SA5.") |
|
} |
|
} |
|
|
|
console.log(""); |
|
console.log(""); |
|
} catch (error) { |
|
console.log(error); |
|
} |
|
}); |
|
|
|
getCert("YOUR_VANMOOF_EMAIL", 'YOUR_VANMOOF_PASSWORD'); |
@Power2All I’m not sure I understand? But yes, your bike does need to be added to your Vanmoof account. If you can use the standard Vanmoof app to access your bike, you should be able to use this script (provided that you are logged in to the same Vanmoof account).