-
-
Save lostmsu/1b0d4a33e5ca2418c2b52797eb720ec7 to your computer and use it in GitHub Desktop.
// License: MIT | |
using System; | |
using System.Collections.Concurrent; | |
using System.IO; | |
using System.Linq; | |
using System.Threading.Tasks; | |
public class LifeSpanTreadmill: IDisposable | |
{ | |
readonly Stream toDevice, fromDevice; | |
readonly byte[] responseBuffer = new byte[8]; | |
volatile bool stop; | |
readonly Task keepAliveLoop; | |
readonly ConcurrentQueue<Action> requests = new ConcurrentQueue<Action>(); | |
public LifeSpanTreadmill(Stream toDevice, Stream fromDevice) { | |
this.toDevice = toDevice ?? throw new ArgumentNullException(nameof(toDevice)); | |
this.fromDevice = fromDevice ?? throw new ArgumentNullException(nameof(fromDevice)); | |
this.keepAliveLoop = Task.Run((Action)this.KeepAliveLoop); | |
} | |
public LifeSpanTreadmill(Stream deviceStream) { | |
this.toDevice = this.fromDevice = deviceStream ?? throw new ArgumentNullException(nameof(deviceStream)); | |
this.keepAliveLoop = Task.Run((Action)this.KeepAliveLoop); | |
} | |
public void Start() => this.SendCommand(Command.Start); | |
public void Stop() => this.SendCommand(Command.Stop); | |
void KeepAliveLoop() { | |
while (!this.stop) { | |
while (this.requests.TryDequeue(out Action action)) | |
action(); | |
this.SendInitSequence(); | |
long speed = this.SendPacket((uint)Command.GetSpeed); | |
} | |
} | |
void SendInitSequence() { | |
long[] resposes = new uint[] { | |
0x20000000, | |
0xC2000000, | |
0xE9FF0000, | |
0xE400F400, | |
}.Select(this.SendPacket).ToArray(); | |
} | |
long SendCommand(Command command) => this.SendCommandAsync(command).Result; | |
Task<long> SendCommandAsync(Command command) { | |
var result = new TaskCompletionSource<long>(); | |
this.requests.Enqueue(() => { | |
try { | |
this.SendInitSequence(); | |
long response = this.SendPacket((uint)command); | |
result.TrySetResult(response); | |
} catch (Exception e) { | |
result.TrySetException(e); | |
} | |
}); | |
return result.Task; | |
} | |
long SendPacket(uint command) { | |
byte[] bytes = BitConverter.GetBytes(command); | |
if (BitConverter.IsLittleEndian) | |
Array.Reverse(bytes); | |
this.toDevice.Write(bytes, 0, 4); | |
this.toDevice.WriteByte(0); | |
this.toDevice.Flush(); | |
int read = this.fromDevice.Read(this.responseBuffer, 0, 6); | |
if (read < 6) | |
throw new NotSupportedException(); | |
long result = BitConverter.ToInt64(this.responseBuffer, 0); | |
return result; | |
} | |
static decimal ToDecimal(long response) => response & 0xFF; | |
public void Dispose() { | |
this.stop = true; | |
this.keepAliveLoop.Wait(); | |
} | |
enum Command: uint | |
{ | |
Start = 0xE1000000, | |
Stop = 0xE0000000, | |
GetSteps = 0xA1880000, | |
GetCalories = 0xA1870000, | |
GetDistance = 0xA1850000, | |
GetTime = 0xA1890000, | |
GetSpeed = 0xA1820000, | |
} | |
} |
@lostmsu do you remember what serial protocol was used?
@lukescott no, I do not. Judging by the year, I might have used the new WinRT APIs to communicate with the Bluetooth device.
@lukescott well, guess what, you are in luck. I dug up the full project: https://github.com/lostmsu/Xrcise
@lostmsu Thank you so much!
Oh I thought your program was serial. It's bluetooth. Dang it. My console is non-bluetooth version :(.
This is a serial version I stumbled across: https://gist.github.com/daeken/a3d3c4da11ca1c2d2b84
Trying to get data over Serial. It's not standard. (My model is TR5000). So far I have discovered pin 2 is COM ground. RS232 COM is pin 5, and RS422/RS485 is pin 1 (I think?). It appears 12 volts powers the console on pin 1. I don't have an Oscilloscope so guessing which pin is what beyond COM with a multimeter is tricky. I was able to find out COM was pin 2 because I took apart the console and did a continuity test on USB ground.
@lukescott this connects to the console via the Bluetooth. The console has to be plugged in. I believe the Bluetooth receiver is in the console.
@lostmsu Yeah, sadly mine doesn't have bluetooth. The refreshed GlowUp versions is Retro without bluetooth or the new Omnihub with bluetooth. When I opened mine up, there is a spot for the bluetooth module that's empty. I got mine second hand, so I didn't really have much choice in what console I got. Good deal.
@lukescott Will a RS-232 Tester work?
https://www.amazon.com/CableMax-RS-232-link-Tester-Female/dp/B004OT995U
@icnocop sadly it’s non standard. Even if it was RS-232, the pins are not where they should be. I don’t have the tools needed to decode the signal. Sticking the wrong voltage on the wrong pins could cause damage. I was lucky to not cause any harm with the probing I did do. - I’m updating my retro console to the Omni hub and giving Bluetooth a shot.
@lukescott by now I don't really remember. Also, one really annoying thing is that I had to also send something to keep connection alive. And as soon as it disconnected, I had to do something on the treadmill to reconnect again.