mirror of
https://github.com/dz0ny/meshcore-sar.git
synced 2026-08-11 16:30:28 +00:00
Warn channels for delayed log rx
This commit is contained in:
@@ -489,7 +489,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 113;
|
CURRENT_PROJECT_VERSION = 115;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
@@ -511,7 +511,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 113;
|
CURRENT_PROJECT_VERSION = 115;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
@@ -530,7 +530,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 113;
|
CURRENT_PROJECT_VERSION = 115;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
@@ -547,7 +547,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 113;
|
CURRENT_PROJECT_VERSION = 115;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
@@ -679,7 +679,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 113;
|
CURRENT_PROJECT_VERSION = 115;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
@@ -702,7 +702,7 @@
|
|||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
CLANG_ENABLE_MODULES = YES;
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CURRENT_PROJECT_VERSION = 113;
|
CURRENT_PROJECT_VERSION = 115;
|
||||||
DEVELOPMENT_TEAM = JND55328G8;
|
DEVELOPMENT_TEAM = JND55328G8;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
|||||||
@@ -43,7 +43,7 @@
|
|||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>113</string>
|
<string>115</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>ITSAppUsesNonExemptEncryption</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
|
|||||||
@@ -5,22 +5,24 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.000231">
|
<testcase classname="fastlane.lanes" name="0: default_platform" time="0.001473">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.67336">
|
<testcase classname="fastlane.lanes" name="1: increment_build_number" time="0.569758">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="2: build_app" time="113.383916">
|
<testcase classname="fastlane.lanes" name="2: build_app" time="95.271262">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="221.37558">
|
<testcase classname="fastlane.lanes" name="3: upload_to_app_store" time="91.795184">
|
||||||
|
|
||||||
|
<failure message="/opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/actions/actions_helper.rb:67:in 'Fastlane::Actions.execute_action' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:255:in 'block in Fastlane::Runner#execute_action' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:229:in 'Dir.chdir' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:229:in 'Fastlane::Runner#execute_action' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:157:in 'Fastlane::Runner#trigger_action_by_name' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/fast_file.rb:159:in 'Fastlane::FastFile#method_missing' Fastfile:23:in 'block (2 levels) in Fastlane::FastFile#parsing_binding' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/lane.rb:41:in 'Fastlane::Lane#call' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:49:in 'block in Fastlane::Runner#execute' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:45:in 'Dir.chdir' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/runner.rb:45:in 'Fastlane::Runner#execute' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/lane_manager.rb:46:in 'Fastlane::LaneManager.cruise_lane' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/command_line_handler.rb:34:in 'Fastlane::CommandLineHandler.handle' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/commands_generator.rb:110:in 'block (2 levels) in Fastlane::CommandsGenerator#run' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/commander-4.6.0/lib/commander/command.rb:187:in 'Commander::Command#call' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/commander-4.6.0/lib/commander/command.rb:157:in 'Commander::Command#run' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/commander-4.6.0/lib/commander/runner.rb:444:in 'Commander::Runner#run_active_command' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb:124:in 'Commander::Runner#run!' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/commander-4.6.0/lib/commander/delegates.rb:18:in 'Commander::Delegates#run!' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/commands_generator.rb:363:in 'Fastlane::CommandsGenerator#run' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/commands_generator.rb:43:in 'Fastlane::CommandsGenerator.start' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/fastlane/lib/fastlane/cli_tools_distributor.rb:132:in 'Fastlane::CLIToolsDistributor.take_off' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/gems/fastlane-2.231.1/bin/fastlane:23:in '<top (required)>' /opt/homebrew/Cellar/ruby/4.0.1/lib/ruby/4.0.0/rubygems.rb:303:in 'Kernel#load' /opt/homebrew/Cellar/ruby/4.0.1/lib/ruby/4.0.0/rubygems.rb:303:in 'Gem.activate_and_load_bin_path' /opt/homebrew/Cellar/fastlane/2.231.1/libexec/bin/fastlane:25:in '<main>' Invalid username and password combination. Used 'hey@dz0n.dev' as the username." />
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,87 @@ class TraceNodeResolver {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static List<ResolvedTraceNode> alignPathSelections({
|
||||||
|
required List<ResolvedTraceNode> nodes,
|
||||||
|
MeshMapNode? startNode,
|
||||||
|
MeshMapNode? endNode,
|
||||||
|
}) {
|
||||||
|
if (nodes.isEmpty || nodes.any((node) => node.candidates.isEmpty)) {
|
||||||
|
return nodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
final candidateCosts = List.generate(
|
||||||
|
nodes.length,
|
||||||
|
(_) => <double>[],
|
||||||
|
growable: false,
|
||||||
|
);
|
||||||
|
final previousChoice = List.generate(
|
||||||
|
nodes.length,
|
||||||
|
(_) => <int>[],
|
||||||
|
growable: false,
|
||||||
|
);
|
||||||
|
|
||||||
|
for (var i = 0; i < nodes.length; i++) {
|
||||||
|
final currentCandidates = nodes[i].candidates;
|
||||||
|
candidateCosts[i] = List<double>.filled(
|
||||||
|
currentCandidates.length,
|
||||||
|
double.infinity,
|
||||||
|
);
|
||||||
|
previousChoice[i] = List<int>.filled(currentCandidates.length, -1);
|
||||||
|
|
||||||
|
for (var j = 0; j < currentCandidates.length; j++) {
|
||||||
|
final current = currentCandidates[j];
|
||||||
|
if (i == 0) {
|
||||||
|
candidateCosts[i][j] = startNode == null
|
||||||
|
? 0
|
||||||
|
: _distanceBetweenNodes(startNode, current);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final previousCandidates = nodes[i - 1].candidates;
|
||||||
|
for (var k = 0; k < previousCandidates.length; k++) {
|
||||||
|
final candidateCost =
|
||||||
|
candidateCosts[i - 1][k] +
|
||||||
|
_distanceBetweenNodes(previousCandidates[k], current);
|
||||||
|
if (candidateCost < candidateCosts[i][j]) {
|
||||||
|
candidateCosts[i][j] = candidateCost;
|
||||||
|
previousChoice[i][j] = k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var bestLastIndex = 0;
|
||||||
|
var bestLastCost = double.infinity;
|
||||||
|
final lastCandidates = nodes.last.candidates;
|
||||||
|
for (var i = 0; i < lastCandidates.length; i++) {
|
||||||
|
final endCost = endNode == null
|
||||||
|
? 0
|
||||||
|
: _distanceBetweenNodes(lastCandidates[i], endNode);
|
||||||
|
final totalCost = candidateCosts.last[i] + endCost;
|
||||||
|
if (totalCost < bestLastCost) {
|
||||||
|
bestLastCost = totalCost;
|
||||||
|
bestLastIndex = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final selectedIndices = List<int>.filled(nodes.length, 0);
|
||||||
|
selectedIndices[nodes.length - 1] = bestLastIndex;
|
||||||
|
for (var i = nodes.length - 1; i > 0; i--) {
|
||||||
|
selectedIndices[i - 1] = previousChoice[i][selectedIndices[i]];
|
||||||
|
}
|
||||||
|
|
||||||
|
return List<ResolvedTraceNode>.generate(nodes.length, (index) {
|
||||||
|
final resolved = nodes[index];
|
||||||
|
return ResolvedTraceNode(
|
||||||
|
candidates: resolved.candidates,
|
||||||
|
matchCount: resolved.matchCount,
|
||||||
|
usedOnlineFallback: resolved.usedOnlineFallback,
|
||||||
|
selectedIndex: selectedIndices[index],
|
||||||
|
);
|
||||||
|
}, growable: false);
|
||||||
|
}
|
||||||
|
|
||||||
static double _scoreNode(
|
static double _scoreNode(
|
||||||
MeshMapNode node, {
|
MeshMapNode node, {
|
||||||
LatLng? referenceA,
|
LatLng? referenceA,
|
||||||
@@ -126,6 +207,14 @@ class TraceNodeResolver {
|
|||||||
return double.maxFinite;
|
return double.maxFinite;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static double _distanceBetweenNodes(MeshMapNode a, MeshMapNode b) {
|
||||||
|
return _distance.as(
|
||||||
|
LengthUnit.Meter,
|
||||||
|
LatLng(a.latitude, a.longitude),
|
||||||
|
LatLng(b.latitude, b.longitude),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static double _distanceToSegmentMeters(LatLng p, LatLng a, LatLng b) {
|
static double _distanceToSegmentMeters(LatLng p, LatLng a, LatLng b) {
|
||||||
final ax = a.longitude;
|
final ax = a.longitude;
|
||||||
final ay = a.latitude;
|
final ay = a.latitude;
|
||||||
|
|||||||
@@ -420,12 +420,17 @@ class _ContactTraceSheetState extends State<ContactTraceSheet> {
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
.toList();
|
.toList();
|
||||||
|
final alignedRelayNodes = TraceNodeResolver.alignPathSelections(
|
||||||
|
nodes: matchedRelayNodes,
|
||||||
|
startNode: senderNode.node,
|
||||||
|
endNode: recipientNode.node,
|
||||||
|
);
|
||||||
|
|
||||||
return _ContactTraceResult(
|
return _ContactTraceResult(
|
||||||
sender: senderNode,
|
sender: senderNode,
|
||||||
recipient: recipientNode,
|
recipient: recipientNode,
|
||||||
routeHashes: routeHashes,
|
routeHashes: routeHashes,
|
||||||
matchedRelayNodes: matchedRelayNodes,
|
matchedRelayNodes: alignedRelayNodes,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -531,12 +531,17 @@ class _MessageTraceSheetState extends State<MessageTraceSheet> {
|
|||||||
senderLatLng: senderLatLng,
|
senderLatLng: senderLatLng,
|
||||||
recipientLatLng: recipientLatLng,
|
recipientLatLng: recipientLatLng,
|
||||||
);
|
);
|
||||||
|
final alignedMatched = TraceNodeResolver.alignPathSelections(
|
||||||
|
nodes: matched,
|
||||||
|
startNode: senderNode.node,
|
||||||
|
endNode: recipientNode.node,
|
||||||
|
);
|
||||||
return _TraceResult(
|
return _TraceResult(
|
||||||
mode: TraceMode.packetPath,
|
mode: TraceMode.packetPath,
|
||||||
sender: senderNode,
|
sender: senderNode,
|
||||||
recipient: recipientNode,
|
recipient: recipientNode,
|
||||||
pathHashes: hopHashes,
|
pathHashes: hopHashes,
|
||||||
matchedPathNodes: matched,
|
matchedPathNodes: alignedMatched,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 2026.0313.1+28
|
version: 2026.0313.2+29
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.9.2
|
sdk: ^3.9.2
|
||||||
|
|||||||
@@ -88,6 +88,65 @@ void main() {
|
|||||||
expect(resolved.cycle().node?.name, 'First Match');
|
expect(resolved.cycle().node?.name, 'First Match');
|
||||||
expect(resolved.cycle().cycle().node?.name, 'Second Match');
|
expect(resolved.cycle().cycle().node?.name, 'Second Match');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('aligns ambiguous hops to the closest continuous path', () {
|
||||||
|
final start = _node(
|
||||||
|
name: 'Start',
|
||||||
|
publicKey: 'start00',
|
||||||
|
latitude: 46.000,
|
||||||
|
longitude: 14.000,
|
||||||
|
);
|
||||||
|
final end = _node(
|
||||||
|
name: 'End',
|
||||||
|
publicKey: 'end000',
|
||||||
|
latitude: 46.300,
|
||||||
|
longitude: 14.300,
|
||||||
|
);
|
||||||
|
final hop1Near = _node(
|
||||||
|
name: 'Hop 1 Near',
|
||||||
|
publicKey: 'aa1100',
|
||||||
|
latitude: 46.100,
|
||||||
|
longitude: 14.100,
|
||||||
|
);
|
||||||
|
final hop1Far = _node(
|
||||||
|
name: 'Hop 1 Far',
|
||||||
|
publicKey: 'aa11ff',
|
||||||
|
latitude: 46.250,
|
||||||
|
longitude: 14.000,
|
||||||
|
);
|
||||||
|
final hop2Near = _node(
|
||||||
|
name: 'Hop 2 Near',
|
||||||
|
publicKey: 'bb2200',
|
||||||
|
latitude: 46.200,
|
||||||
|
longitude: 14.200,
|
||||||
|
);
|
||||||
|
final hop2Far = _node(
|
||||||
|
name: 'Hop 2 Far',
|
||||||
|
publicKey: 'bb22ff',
|
||||||
|
latitude: 46.050,
|
||||||
|
longitude: 14.280,
|
||||||
|
);
|
||||||
|
|
||||||
|
final aligned = TraceNodeResolver.alignPathSelections(
|
||||||
|
nodes: [
|
||||||
|
TraceNodeResolver.resolveBest(
|
||||||
|
nodes: [hop1Far, hop1Near],
|
||||||
|
localPublicKeys: {hop1Near.publicKey, hop1Far.publicKey},
|
||||||
|
prefixHex: 'aa11',
|
||||||
|
),
|
||||||
|
TraceNodeResolver.resolveBest(
|
||||||
|
nodes: [hop2Far, hop2Near],
|
||||||
|
localPublicKeys: {hop2Near.publicKey, hop2Far.publicKey},
|
||||||
|
prefixHex: 'bb22',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
startNode: start,
|
||||||
|
endNode: end,
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(aligned[0].node?.name, 'Hop 1 Near');
|
||||||
|
expect(aligned[1].node?.name, 'Hop 2 Near');
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
MeshMapNode _node({
|
MeshMapNode _node({
|
||||||
|
|||||||
Reference in New Issue
Block a user