Skip to content

Commit

Permalink
Merge pull request #517 from doudar/ConfigApp
Browse files Browse the repository at this point in the history
Config app
  • Loading branch information
doudar authored Mar 14, 2024
2 parents fc235a5 + 1fe42ba commit 183cd74
Show file tree
Hide file tree
Showing 29 changed files with 1,848 additions and 1,176 deletions.
Binary file added .DS_Store
Binary file not shown.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ include/telegram_token.h
Errors
SmartSpin_logfile.txt
*.err
.DS_Store
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,5 +82,6 @@
"userconfig",
"VERSIONFILE",
"WEBSERVER"
]
],
"cmake.configureOnOpen": true
}
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
### Added
- Added pass through shifting in both ERG and SIM mode.
- Refined and added BLE custom characteristics for upcoming configuration app.
-
### Changed
- Updated communications overview picture.
- Updated kit purchasing links.
Expand All @@ -15,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Switched from using Power Table to a Torque Table for better compensation in cad variations.
- added test for invalid Peloton data to keep stepper from running away without resistance information.
- Fixed a bug with Trainer Day and rapid ERG sending.
- Many updates and bug fixes which enable the Config App to communicate with SmartSpin2k.

### Hardware
- added Yesoul S3
Expand Down
Binary file modified Pictures/ss2k_wiki_banner.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added Pictures/ss2k_wiki_banner.xcf
Binary file not shown.
Binary file added Pictures/ss2kv3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 0 additions & 5 deletions data/settings.html
Original file line number Diff line number Diff line change
Expand Up @@ -259,10 +259,6 @@ <h2>
<p class="tooltip">Enable BLE RX Logging<span class="tooltiptext">Enable logging BLE RX messages.
Uses lots of bandwidth.</span></p>
</td>
<td>
<label class="switch"><input type="checkbox" name="logComm" id="logComm"><span
class="slider"></span></label>
</td>
</tr>
</tbody>
</table>
Expand Down Expand Up @@ -334,7 +330,6 @@ <h2>
document.getElementById("stepperDir").checked = obj.stepperDir;
document.getElementById("shifterDir").checked = obj.shifterDir;
document.getElementById("udpLogEnabled").checked = !!obj.udpLogEnabled;
document.getElementById("logComm").checked = !!obj.logComm;
updateSlider(document.getElementById("shiftStep").value, document.getElementById("shiftStepValue"));
updateSlider(document.getElementById("inclineMultiplier").value, document.getElementById("inclineMultiplierValue"));
updateSlider(document.getElementById("ERGSensitivity").value, document.getElementById("ERGSensitivityValue"));
Expand Down
85 changes: 38 additions & 47 deletions include/BLE_Common.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,35 +22,6 @@
#define FMTS_SERVER_LOG_TAG "FTMS_SERVER"
#define CUSTOM_CHAR_LOG_TAG "Custom_C"

// custom characteristic codes
#define BLE_firmwareUpdateURL 0x01
#define BLE_incline 0x02
#define BLE_simulatedWatts 0x03
#define BLE_simulatedHr 0x04
#define BLE_simulatedCad 0x05
#define BLE_simulatedSpeed 0x06
#define BLE_deviceName 0x07
#define BLE_shiftStep 0x08
#define BLE_stepperPower 0x09
#define BLE_stealthChop 0x0A
#define BLE_inclineMultiplier 0x0B
#define BLE_powerCorrectionFactor 0x0C
#define BLE_simulateHr 0x0D
#define BLE_simulateWatts 0x0E
#define BLE_simulateCad 0x0F
#define BLE_FTMSMode 0x10
#define BLE_autoUpdate 0x11
#define BLE_ssid 0x12
#define BLE_password 0x13
#define BLE_foundDevices 0x14
#define BLE_connectedPowerMeter 0x15
#define BLE_connectedHeartMonitor 0x16
#define BLE_shifterPosition 0x17
#define BLE_saveToLittleFS 0x18
#define BLE_targetPosition 0x19
#define BLE_externalControl 0x1A
#define BLE_syncMode 0x1B

// macros to convert different types of bytes into int The naming here sucks and
// should be fixed.
#define bytes_to_s16(MSB, LSB) (((signed int)((signed char)MSB))) << 8 | (((signed char)LSB))
Expand Down Expand Up @@ -83,6 +54,16 @@ class ss2kCustomCharacteristicCallbacks : public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *);
};

class ss2kCustomCharacteristic {
public:
//Used internally for notify and onWrite Callback.
static void process(std::string rxValue);
//Custom Characteristic value that needs to be notified
static void notify(const uint8_t _item);
// Notify any changed value in userConfig
static void parseNemit();
};

extern std::string FTMSWrite;

// TODO add the rest of the server to this class
Expand All @@ -93,7 +74,7 @@ class SpinBLEServer {
bool CyclingPowerMeasurement : 1;
bool IndoorBikeData : 1;
} clientSubscribed;

NimBLEServer *pServer = nullptr;
void setClientSubscribed(NimBLEUUID pUUID, bool subscribe);
void notifyShift();

Expand All @@ -114,6 +95,9 @@ int connectedClientCount();
void controlPointIndicate();
void processFTMSWrite();

// BLE FIRMWARE UPDATER
void BLEFirmwareSetup();

// *****************************Client*****************************

// Keeping the task outside the class so we don't need a mask.
Expand All @@ -136,6 +120,8 @@ class SpinBLEAdvertisedDevice {
private:
QueueHandle_t dataBufferQueue = nullptr;

bool isPostConnected = false;

public: // eventually these should be made private
// // TODO: Do we dispose of this object? Is so, we need to de-allocate the queue.
// // This distructor was called too early and the queue was deleted out from
Expand All @@ -159,7 +145,8 @@ class SpinBLEAdvertisedDevice {
bool isCT = false;
bool isRemote = false;
bool doConnect = false;
bool postConnected = false;
void setPostConnected(bool pc) { isPostConnected = pc; }
bool getPostConnected() { return isPostConnected; }
void set(BLEAdvertisedDevice *device, int id = BLE_HS_CONN_HANDLE_NONE, BLEUUID inServiceUUID = (uint16_t)0x0000, BLEUUID inCharUUID = (uint16_t)0x0000);
void reset();
void print();
Expand All @@ -169,21 +156,20 @@ class SpinBLEAdvertisedDevice {

class SpinBLEClient {
private:

public: // Not all of these need to be public. This should be cleaned up
// later.
boolean connectedPM = false;
boolean connectedHRM = false;
boolean connectedCD = false;
boolean connectedCT = false;
boolean connectedRemote = false;
boolean doScan = false;
bool dontBlockScan = true;
bool intentionalDisconnect = false;
int noReadingIn = 0;
int cscCumulativeCrankRev = 0;
int cscLastCrankEvtTime = 0;
int reconnectTries = MAX_RECONNECT_TRIES;
boolean connectedPM = false;
boolean connectedHRM = false;
boolean connectedCD = false;
boolean connectedCT = false;
boolean connectedRemote = false;
boolean doScan = false;
bool dontBlockScan = true;
int intentionalDisconnect = 0;
int noReadingIn = 0;
int cscCumulativeCrankRev = 0;
int cscLastCrankEvtTime = 0;
int reconnectTries = MAX_RECONNECT_TRIES;

BLERemoteCharacteristic *pRemoteCharacteristic = nullptr;

Expand All @@ -193,17 +179,22 @@ class SpinBLEClient {
void start();
// void serverScan(bool connectRequest);
bool connectToServer();
void scanProcess(int duration = DEFAULT_SCAN_DURATION);
// Check for duplicate services of BLEClient and remove the previously
// connected one.
void removeDuplicates(NimBLEClient *pClient);
void resetDevices(NimBLEClient *pClient);
void postConnect();
void FTMSControlPointWrite(const uint8_t* pData, int length);
void FTMSControlPointWrite(const uint8_t *pData, int length);
void connectBLE_HID(NimBLEClient *pClient);
void keepAliveBLE_HID(NimBLEClient *pClient);
void checkBLEReconnect();
void handleBattInfo(NimBLEClient *pClient, bool updateNow);
// Instead of using this directly, set the .doScan flag to start a scan.
void scanProcess(int duration = DEFAULT_SCAN_DURATION);
void checkBLEReconnect();
// Disconnects all devices. They will then be reconnected if scanned and preferred again.
void reconnectAllDevices();

String adevName2UniqueName(NimBLEAdvertisedDevice *inDev);
};

class MyAdvertisedDeviceCallback : public NimBLEAdvertisedDeviceCallbacks {
Expand Down
172 changes: 85 additions & 87 deletions include/Builtin_Pages.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,99 +5,97 @@
* SPDX-License-Identifier: GPL-2.0-only
*/

// OTA Update pages. Not stored in LittleFS because we will use this to restore
// the webserver files if they get corrupt.
/* Style */
#pragma once

#include <Arduino.h>

String OTAStyle = "<style>#file-input,input{width:100%;height:44px;border-radius:4px;margin:"
"10px auto;font-size:15px}"
"input{background:#f1f1f1;border:0;padding:0 "
"15px}body{background:#031cbd;font-family:sans-serif;font-size:14px;color:#"
"777}"
"#file-input{padding:0;border:1px solid "
"#ddd;line-height:44px;text-align:left;display:block;cursor:pointer}"
"#bar,#prgbar{background-color:#f1f1f1;border-radius:10px}#bar{background-"
"color:#3498db;width:0%;height:10px}"
"form{background:#fff;max-width:258px;margin:75px "
"auto;padding:30px;border-radius:5px;text-align:center}"
".btn{background:#031cbd;color:#fff;cursor:pointer}</style>";
String OTAStyle =
"<style>"
"body{background-color:#f0f0f0;font-family:Arial, sans-serif;font-size:14px;color:#333;}"
"#file-input,input{width:90%;height:44px;border-radius:4px;margin:10px 5%;font-size:15px;}"
"input{background:#ffffff;border:1px solid #ddd;padding:0 15px;}"
"#file-input{line-height:44px;text-align:left;display:block;cursor:pointer;color:#333;}"
"#bar,#prgbar{background-color:#e0e0e0;border-radius:10px;}"
"#bar{background-color:#4CAF50;width:0%;height:20px;}"
"form{background:#ffffff;max-width:300px;margin:50px auto;padding:20px;border-radius:8px;text-align:center;box-shadow: 0 4px 8px rgba(0,0,0,0.1);}"
".btn{background:#007BFF;color:#ffffff;cursor:pointer;border:none;padding:10px 15px;border-radius:5px;}"
".btn:hover{background:#0056b3;}"
"</style>";

/* Login page */
String OTALoginIndex = "<form name=loginForm>"
"<h1>ESP32 Login</h1>"
"<input name=userid placeholder='User ID'> "
"<input name=pwd placeholder=Password type=Password> "
"<input type=submit onclick=check(this.form) class=btn value=Login></form>"
"<script>"
"function check(form) {"
"if(form.userid.value=='admin' && form.pwd.value=='admin')"
"{window.open('/OTAIndex')}"
"else"
"{alert('Error Password or Username')}"
"}"
"</script>" +
OTAStyle;
String OTALoginIndex =
"<form name='loginForm'>"
"<h1>Firmware Update Login</h1>"
"<input name='userid' placeholder='User ID'> "
"<input name='pwd' placeholder='Password'> "
"<input type='submit' onclick='check(this.form)' class='btn' value='Login'>"
"</form>"
"<script>"
"function check(form) {"
"if(form.userid.value=='admin' && form.pwd.value=='admin'){"
"window.open('/OTAIndex');"
"}else{"
"alert('Error: Incorrect Username or Password');"
"}"
"}"
"</script>" +
OTAStyle;

String noIndexHTML = "<!DOCTYPE html>"
"<html>"
"<body>"
"<h2>The webserver files <br>need to be updated.</h2>"
"Please enter the credentials for your network <br>or upload a new "
"filesystem image using the <br>link below."
"<head>"
" <title>SmartSpin2K Web Server</title>"
"</head>"
"<body>"
"<form action='/send_settings'>"
"<p><label for='ssid'>SSID</label></p>"
"<input type='text' id='ssid' name='ssid' value='' />"
"<label for='password'>Password</label>"
"<input type='text' id='password' name='password' value='' />"
"<input type='submit' value='Submit' />"
"</form>"
"<form action='/reboot.html'>"
"<input type='submit' value='Reboot!'>"
"</form>"
"<p style='text-align: center;'><strong><a href='login'>Update "
"Firmware</a></strong></p></h2>"
"</body>"
"</html> " +
OTAStyle;
String noIndexHTML =
"<!DOCTYPE html>"
"<html>"
"<body>"
"<h2>The webserver files need to be updated.</h2>"
"Please enter the credentials for your network or upload a new filesystem image using the link below."
"<form action='/send_settings'>"
"<p><label for='ssid'>SSID:</label></p>"
"<input type='text' id='ssid' name='ssid' value='' />"
"<p><label for='password'>Password:</label></p>"
"<input type='password' id='password' name='password' value='' />"
"<input type='submit' value='Submit' class='btn'/>"
"</form>"
"<form action='/reboot.html'>"
"<input type='submit' value='Reboot!' class='btn'/>"
"</form>"
"<p style='text-align: center;'><strong><a href='login'>Update Firmware</a></strong></p>"
"</body>"
"</html> " +
OTAStyle;

/* Server Index Page */
String OTAServerIndex = "<body style='font-family: Verdana,sans-serif; font-size: 14px;'>"
"<div style='width:400px;padding:20px;border-radius:10px;border:solid 2px #e0e0e0;margin:auto;margin-top:20px;'>"
"<div style='width:100%;text-align:center;font-size:18px;font-weight:bold;margin-bottom:12px;'>SmartSpin2k OTA</div>"
"<form method='POST' action='#' enctype='multipart/form-data' id='upload-form' style='width:100%;margin-bottom:8px;'>"
"<input type='file' name='update'>"
"<input type='submit' value='Update' style='float:right;'>"
"</form>"
"<div style='width:100%;background-color:#e0e0e0;border-radius:8px;'>"
"<div id='prg' style='width:0%;background-color:#2196F3;padding:2px;border-radius:8px;color:white;text-align:center;'>0%</div>"
"</div>"
"<div>Valid files are firmware.bin or littlefs.bin</div>"
"</div>"
"</body>"
"<script>"
"var prg = document.getElementById('prg');"
"var form = document.getElementById('upload-form');"
"form.addEventListener('submit', e=>{"
"e.preventDefault();"
"var data = new FormData(form);"
"var req = new XMLHttpRequest();"
"req.open('POST', '/update');"
"req.upload.addEventListener('progress', p=>{"
"let w = Math.round((p.loaded / p.total)*100) + '%';"
"if(p.lengthComputable){"
"prg.innerHTML = w;"
"prg.style.width = w;"
"}"
"if(w == '100%'){ prg.style.backgroundColor = '#04AA6D';"
"prg.innerHTML = 'Success! You can leave this page.';}"
"});"
"req.send(data);"
"});"
"</script>";
String OTAServerIndex =
"<body>"
"<div style='width:400px;padding:20px;border-radius:10px;border:solid 2px #e0e0e0;margin:auto;margin-top:20px;background-color:#fff;'>"
"<div style='text-align:center;font-size:18px;font-weight:bold;margin-bottom:12px;'>SmartSpin2k OTA</div>"
"<form method='POST' action='#' enctype='multipart/form-data' id='upload-form'>"
"<input type='file' name='update' style='margin-bottom:10px;'>"
"<input type='submit' value='Update' class='btn' style='width:100%;'>"
"</form>"
"<div style='background-color:#e0e0e0;border-radius:8px;margin-top:10px;'>"
"<div id='prg' style='width:0%;background-color:#4CAF50;padding:2px;border-radius:8px;color:white;text-align:center;'>0%</div>"
"</div>"
"<div>Valid files are firmware.bin or littlefs.bin</div>"
"</div>"
"</body>"
"<script>"
"var prg = document.getElementById('prg');"
"var form = document.getElementById('upload-form');"
"form.addEventListener('submit', e=>{"
"e.preventDefault();"
"var data = new FormData(form);"
"var req = new XMLHttpRequest();"
"req.open('POST', '/update');"
"req.upload.addEventListener('progress', p=>{"
"let w = Math.round((p.loaded / p.total)*100) + '%';"
"if(p.lengthComputable){"
"prg.innerHTML = w;"
"prg.style.width = w;"
"}"
"if(w == '100%'){"
"prg.style.backgroundColor = '#04AA6D';"
"prg.innerHTML = 'Success! You can leave this page.';"
"}"
"});"
"req.send(data);"
"});"
"</script>";
Loading

0 comments on commit 183cd74

Please sign in to comment.