Non-Linux Dev Envs 0.9.8#232
Non-Linux Dev Envs 0.9.8#232DXCanas wants to merge 11 commits intoJaapvanEkris:0.9.8-In-Developmentfrom
Conversation
…y with graceful fallbacks Changed BleManager to lazy-load native modules only on Linux platform and throw descriptive error on unsupported platforms. Updated PeripheralManager error handling to downgrade BLE initialization errors from error to warn level and automatically disable BLE/HRM modes when unavailable. Made GPIO timer service conditional on Linux platform in server.js with warning message for other platforms.
Introduces the `simulateWithoutHardware` flag to the default configuration and config validation. This enables developers to bypass GPIO and BLE hardware checks to simulate the environment on headless servers or non-Linux systems without causing error logs. AI-assisted-by: Gemini 3.1 Pro
Removes the static `process.platform === 'linux'` check in favor of dynamically importing `hci-socket` and `ble-host`. Uses the new `simulateWithoutHardware` config flag to bypass BLE initialization when requested. Refactors `open()` to use guard clauses, preventing deep nesting and improving readability. Catches and logs missing dependencies cleanly. AI-assisted-by: Gemini 3.1 Pro
Removes the static `process.platform === 'linux'` check from `server.js` and moves hardware checking into `GpioTimerService.js`. Uses dynamic imports for `pigpio` wrapped in a try/catch block. If `simulateWithoutHardware` is true or if `pigpio` fails to load (e.g., on non-Raspberry Pi devices or without root), the service logs a warning and exits cleanly instead of crashing the app. AI-assisted-by: Gemini 3.1 Pro
Updates `GpioTimerService` to explicitly read `/proc/device-tree/model` to confirm it is running on a supported Raspberry Pi (3, 4, or Zero 2W) before attempting to load `pigpio`. Updates `BleManager` to explicitly check for Linux before attempting to load `hci-socket`. Both services now log explicit messages detailing their initialization decisions as requested by maintainers, ensuring clear visibility into why hardware modules are bypassed or loaded. AI-assisted-by: Gemini 3.1 Pro
…on failure gracefully The `pigpio` JS wrapper exports functions even if the underlying C library fails to initialize (e.g. on macOS or non-Pi Linux without root), causing a hard crash later when those undefined C-bindings are called. This commit explicitly wraps the first call to `pigpio.hardwareRevision()` in a try/catch block to catch the `TypeError: is not a function`. This prevents the application from crashing and instead cleanly bypasses the GPIO service as requested by maintainers. AI-assisted-by: Gemini 3.1 Pro
… JSDoc imports Replaces the temporary `any` types with `typeof import(...)` for the BLE modules (`hci-socket` and `ble-host`). This restores strong type checking for the class properties while keeping the actual module loading deferred to runtime, satisfying the requirement to lazy-load these modules only on supported platforms (Linux) without losing static analysis benefits.
This reverts commit 5a352e5.
…T+ initialization attempts Relocates the `simulateWithoutHardware` check from individual BLE peripheral setup() functions to the `createBlePeripheral()` and `createAntPeripheral()` functions in PeripheralManager. This prevents BLE and ANT+ peripherals from being created at all when hardware simulation is enabled, rather than catching rejected promises after initialization has already started. Removes now-unnecessary .catch() handlers
|
I'm a bit puzzled here. I see a lit of changes, just to essentially comment out the peripheralmanager and gpio. Why such an elaborate approach? |
|
The approach became more elaborate with iterations on the PR, but started off more-or-less simply: It's been a while now so the memory is no longer fresh. But from what I recall, there were many chunks of code to comment out, I kept hitting more and more errors I made my way through, and it was a pain to pull changes straight into the pi after working on my laptop (or vise versa). So I started with just catching the errors and then had claude come in to refine. And then introduced new features for the other use cases described in #194 |
|
I'm not too happy about spreading this simulation/disabling logic across many parts of the code. It makes debugging tough. As you are already conditionally loading stuff, why not load dummy modules. In fact that may be a nice abstraction (as gpio might load the replay functionality that curremtly is commented out in server.js), and still provide decent feedback (peripheralmanager needs BLE to respond to changes initiated by the GUI). By doing so, you can introduce two config options: one for simulated gpio (replacing gpio with replay) and one for simulating BLE and ANT+. A trick I use is also to listen to metrics and report (80 + 0.5 * Power) as heartrate. I would keep MQTT in there as it allows simulating commands. You could even use existing parameters: gpiopin could ve set to "sim", as would BLE type. |
|
I disagree with Jaap. I think this is not a lot of change. It seems a lot because there is a lot of logic that relates to logging (whether it provide benefit or not its up for debate) and error handling which was missing in the past because the hard assumption was that we have these HW modules (and in case of missing these modules the app would have crashed, even the unit tests were throwing hci-socket missing error for me because the dev container does not have bluetooth installed which can be done of course). Also I dont see how this makes debugging any more difficult: basically you have a flag in the settings (that defaults to false) that disables all hardwares. Having mock modules would actually be more complicated in my view and would require more change. We would need to conditionally load those and maintain its public interface manually that is a lot of work for little benefit (please see more on that below). I think the long term goal for testing the client is not by running the back end and have these mock BLE and ANT that mimic the behaviour. This is just added complexity and we do not need that. The Client responsibility ends at the level of the WebSocket command. It should send the appropriate command and should react to things coming from the WS. The rest is backend staff which we are not testing when client is being worked on. Having the need to launch the back-end for client development is rather bad design (though currently it is a necessity to some extent). The better approach and this is what we should be using on the long term (once I have the TS/vite/vitest migration which I have started and seems simpler than I thought) we would mock the WebSocket and catch the commands there and provide mock responses, but this is also only in integration kind of tests not on the unit test level.
For the client development this does not add any benefit as we should not be testing with actual BLE and ANT+ simulation on the back end. Its simply not necessary. For the back-end development this could be necessary I agree there. But please bear in mind that vitests supports module import mocking which would solve all these problems. Mocking can be driven by the flags, It does not even need to be a config flag, can be an env variable or a command line argument (like DEBUG or SIMULATE). As a side note, I have been thinking about this every time I need to run simulation that the comment out simulation is not very user friendly (one needs to make sure that the commenting out is not accidentally committed) that we can drive the simulation with an env variable or a command line argument (including the time delay, the file name etc.). This would allow to create a npm run TARGET for simple start. |
#194, retargetted to 0.9.8 :)
Please do confirm functionality; this was a rush job during my lunch break and the rebase got funky.