-
-
Notifications
You must be signed in to change notification settings - Fork 48
Expand file tree
/
Copy pathBLE_Zwift_Service.h
More file actions
121 lines (91 loc) · 4.21 KB
/
BLE_Zwift_Service.h
File metadata and controls
121 lines (91 loc) · 4.21 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/*
* Copyright (C) 2020 Anthony Doud & Joel Baranick
* All rights reserved
*
* SPDX-License-Identifier: GPL-2.0-only
*/
#pragma once
#include <NimBLEDevice.h>
#include "Zwift_Protocol_Messages.h"
// Zwift manufacturer ID
inline constexpr uint16_t kZwiftManufacturerId = 0x094A;
// Zwift device type identifiers (from manufacturer data)
enum class ZwiftDeviceType : uint8_t {
BC1 = 0x09,
ClickV2Right = 0x0A,
ClickV2Left = 0x0B,
};
// Keepalive / riding data interval in milliseconds
inline constexpr unsigned long kZwiftKeepaliveIntervalMs = 5000;
inline constexpr unsigned long kZwiftSessionTimeoutMs = kZwiftKeepaliveIntervalMs * 2;
inline constexpr unsigned long kZwiftRidingDataIntervalMs = 250;
inline constexpr char kZwiftBleLogTag[] = "BLE_Zwift";
inline constexpr char kZwiftDirConLogTag[] = "DRC_Zwift";
class BLE_Zwift_Service {
public:
BLE_Zwift_Service();
void setupService(NimBLEServer *pServer);
void update();
// Returns true if a Zwift client has been used recently.
bool isConnected();
// Returns the current virtual gear ratio x10000 (0 = no virtual shifting active)
uint32_t getGearRatioX10000();
// Send a shift up notification to Zwift (key down + key up)
void sendShiftUp();
// Send a shift down notification to Zwift (key down + key up)
void sendShiftDown();
// Handle incoming write to sync_rx (handshake and protocol commands)
// isDirCon=true uses trainer protocol, isDirCon=false uses Click v2 controller protocol
void handleSyncRxWrite(const std::string &value, bool isDirCon = false);
private:
NimBLEService *pZwiftService;
NimBLECharacteristic *asyncCharacteristic;
NimBLECharacteristic *syncRxCharacteristic;
NimBLECharacteristic *syncTxCharacteristic;
NimBLECharacteristic *unknownCharacteristic5;
NimBLECharacteristic *unknownCharacteristic6;
bool isDirCon;
unsigned long _lastActivityTime;
unsigned long _lastKeepaliveTime;
unsigned long _lastRidingDataTime;
uint32_t _gearRatioX10000;
const char *getLogTag() const;
bool keepAlive(unsigned long now);
void resetSession();
// Encode a button mask into a protobuf varint message and send as notification
void sendButtonNotification(ZwiftProtocol::RideButtonMask buttonMask);
// Encode uint32 as protobuf varint, returns number of bytes written
static size_t encodeVarint32(uint32_t value, uint8_t *buffer);
// Encode uint64 as ULEB128 varint, returns number of bytes written
static size_t encodeUleb128(uint64_t value, uint8_t *buffer);
// Returns the number of bytes a ULEB128-encoded value would occupy
static size_t encodeUleb128Len(uint64_t value);
// Decode ULEB128 varint from buffer, returns number of bytes consumed
static size_t decodeUleb128(const uint8_t *buf, size_t bufLen, uint64_t *result);
// Send the "all buttons released" state
void sendAllButtonsReleased();
// Send a fully-built payload on sync_tx and mirror it through DirCon.
void sendSyncTxPayload(const uint8_t *payload, size_t length);
// Send a fully-built payload on async and mirror it through DirCon.
void sendAsyncPayload(const uint8_t *payload, size_t length);
// Send current GearRatio device information on sync_tx.
void sendGearRatioSyncTx();
// Send current GeneralInfo device information on sync_tx.
void sendGeneralInfoSyncTx();
// Send TRAINER_CONFIG_STATUS category 2 with reported real/virtual gear ratios.
void sendTrainerConfigSimulationStatus(uint32_t realGearRatioX10000, uint32_t virtualGearRatioX10000);
// Send TRAINER_CONFIG_STATUS category 3 with virtual_shifting_mode=1 on async.
void sendTrainerConfigVirtualShiftStatus(uint8_t virtualShiftingMode = 1);
// Handle Zwift trainer protocol command (non-RideOn messages)
void handleZwiftCommand(const uint8_t *data, size_t length);
// Apply received gear ratio to shifter position
void applyGearRatio();
friend class ZwiftSyncRxCallbacks;
};
// Callback class for the Zwift sync_rx characteristic writes
class ZwiftSyncRxCallbacks : public NimBLECharacteristicCallbacks {
public:
void onWrite(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo) override;
void onSubscribe(NimBLECharacteristic *pCharacteristic, NimBLEConnInfo &connInfo, uint16_t subValue) override;
};
extern BLE_Zwift_Service zwiftService;