Skip to content

[PoC] LEGO Technice Move hub improvements#217

Draft
vicocz wants to merge 6 commits intodefaultfrom
local/tehnice-move-hub-improvements
Draft

[PoC] LEGO Technice Move hub improvements#217
vicocz wants to merge 6 commits intodefaultfrom
local/tehnice-move-hub-improvements

Conversation

@vicocz
Copy link
Copy Markdown
Owner

@vicocz vicocz commented Apr 2, 2026

No description provided.

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR refactors LEGO Powered Up / Control+ Bluetooth device handling by introducing a shared base class for GATT characteristic setup + hub property processing, and adds a PoC calibration flow for Technic Move steering so ABS-position commands work correctly outside PLAYVM mode.

Changes:

  • Add ControlPlusDeviceBase to centralize characteristic discovery/notification setup and hub property requests/parsing.
  • Add a shared NormalizeAngle helper in LegoWirelessProtocol and refactor parsing / byte conversions to use span-based helpers.
  • Update TechnicMoveDevice steering to apply a calibrated zero offset in non-PLAYVM mode and adjust port setup to query APOS before enabling POS notifications.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
BrickController2/BrickController2/Protocols/LegoWirelessProtocol.cs Adds shared NormalizeAngle helper for angle math.
BrickController2/BrickController2/DeviceManagement/TechnicMoveDevice.cs Implements non-PLAYVM steering calibration + offset application and LED cleanup on disconnect.
BrickController2/BrickController2/DeviceManagement/Lego/RemoteControl.cs Switches RemoteControl to the new shared Control+ base and reuses hub property handling.
BrickController2/BrickController2/DeviceManagement/Lego/ControlPlusDeviceBase.cs New base class for characteristic setup, write helpers, and hub property request/parse logic.
BrickController2/BrickController2/DeviceManagement/ControlPlusDevice.cs Migrates to new base class, refactors parsing to spans, and routes writes through shared helpers.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +117 to +126
if (angle >= 180)
{
return angle - (360 * ((angle + 180) / 360));
}
else if (angle < -180)
{
return angle + (360 * ((180 - angle) / 360));
}

return angle;
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NormalizeAngle does not correctly normalize angles less than -180 for values beyond one full rotation (e.g., angle = -540 currently returns 180, which is outside the intended [-180, 179] range). This can lead to incorrect servo/steering calculations when angles accumulate beyond a single turn. Consider replacing this with a modulo-based normalization that always maps into [-180, 179] (e.g., using ((angle + 180) % 360 + 360) % 360 - 180).

Suggested change
if (angle >= 180)
{
return angle - (360 * ((angle + 180) / 360));
}
else if (angle < -180)
{
return angle + (360 * ((180 - angle) / 360));
}
return angle;
return ((angle + 180) % 360 + 360) % 360 - 180;

Copilot uses AI. Check for mistakes.
return;
}

var dataLength = data[0];
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dataLength is assigned but never used, which will generate an "unused variable" warning. Either remove it or use it to validate data.Length matches the reported length (if that was the intent).

Suggested change
var dataLength = data[0];
var dataLength = data[0];
if (dataLength != data.Length)
{
return;
}

Copilot uses AI. Check for mistakes.
_virtualPortSendBuffer[7] = (byte)(value2 < 0 ? (255 + value2) : value2);

if (await _bleDevice!.WriteNoResponseAsync(_characteristic!, _virtualPortSendBuffer, token))
if (await WriteAsync(_virtualPortSendBuffer, token))
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This virtual port path switched from a no-response write to WriteAsync (write-with-response). For high-frequency output updates, this can significantly reduce throughput and increase latency. If the protocol doesn’t require an ACK here, consider using WriteNoResponseAsync (or a dedicated helper) to preserve the previous behavior/performance characteristics.

Suggested change
if (await WriteAsync(_virtualPortSendBuffer, token))
if (await WriteNoResponseAsync(_virtualPortSendBuffer, token))

Copilot uses AI. Check for mistakes.
Comment on lines +212 to +221
// query current APOS
await WriteAsync([0x05, 0x00, 0x21, portId, 0x00], token);
await Task.Delay(250, token); //TODO wait for change

// setup channel to report POS position regularly
await WriteAsync(inputFormatForRelAngle, token);
await Task.Delay(250, token); //TODO wait for change

// need to recalculate base angle to support ABS POS commands
_calibratedZeroAngle = CalculateCalibratedTarget(channel);
Copy link

Copilot AI Apr 2, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Calibration currently relies on fixed delays after requesting APOS/POS (with TODOs) and then immediately computes _calibratedZeroAngle. If the hub response is delayed or dropped, calibration will be computed from stale/default _absolutePositions / _relativePositions values. Consider waiting for the actual port-value message(s) (e.g., via a TaskCompletionSource triggered in OnCharacteristicChanged, or by polling _positionUpdateTimes with a timeout) before calculating the calibrated target.

Copilot uses AI. Check for mistakes.
@vicocz vicocz changed the title [PoC] Local/tehnice move hub improvements [PoC] LEGO Technice Move hub improvements Apr 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants