根据 RSSI 值找到标签最近的嗅探器

Find the closest sniffer for a tag according to RSSI value

我有一个场景,我正在跟踪网状网络中的蓝牙标签,我想知道在任何给定的时间点,标签最接近哪个nodeId(嗅探器)(根据rssi 值)。

给定 运行 window 数据传入:

{ mac: '123', nodeId: 1, rssi: 1 }
{ mac: '456', nodeId: 2, rssi: 3 }

我的想法是我想从 mac 中获取最新的 3 个读数,找到具有最高 rssi 值的那个,然后输出它,并且只有当它改变了 nodeIdmac 来自最后一个输出。我有下面的代码,它几乎就在那里,但是当有多个 mac 地址时,事情开始变得混乱。

你能给我指个方向吗?我想我也需要按 Mac 分组?

const { from } = require('rxjs');
const {
  window,
  map,
  windowCount,
  mergeAll,
  max,
  distinctUntilKeyChanged,
  groupBy,
  mergeMap,
  toArray
} = require('rxjs/operators');

const source = from([
  { mac: '123', nodeId: 1, rssi: 1 },
  { mac: '123', nodeId: 2, rssi: 2 },
  { mac: '123', nodeId: 1, rssi: 4 },
  { mac: '123', nodeId: 1, rssi: 3 },
  { mac: '123', nodeId: 3, rssi: 2 },
  { mac: '123', nodeId: 1, rssi: 2 },
  { mac: '123', nodeId: 1, rssi: 8 },
  { mac: '123', nodeId: 2, rssi: 8 },
  { mac: '456', nodeId: 2, rssi: 10 },
  { mac: '123', nodeId: 2, rssi: 11 },
  { mac: '123', nodeId: 3, rssi: 9 },
  { mac: '456', nodeId: 3, rssi: 9 },
  { mac: '123', nodeId: 2, rssi: 11 },
  { mac: '123', nodeId: 3, rssi: 9 },
  { mac: '456', nodeId: 3, rssi: 9 },
  { mac: '123', nodeId: 3, rssi: 10 }
]);

const GROUP_BY = 'nodeId';
const COMPARE_KEY = 'rssi';
const WINDOW = 3;

const comparer = field => (a, b) => (a[field] < b[field] ? -1 : 1);

source
  .pipe(
    groupBy(metric => metric[GROUP_BY]),
    mergeMap(group => group.pipe(toArray())),
    mergeAll(),
    windowCount(WINDOW),
    map(metric => metric.pipe(max(comparer(COMPARE_KEY)))),
    mergeAll(),
    distinctUntilKeyChanged(COMPARE_KEY)
  )
  .subscribe(e => {
    console.log(e);
  });

编辑 @Dorus 太棒了,把它全部清理干净了,这似乎可以解决问题:

const GROUP_BY = 'mac';
const COMPARE_KEY = 'rssi';
const BUFFER_SIZE = 3;
const DISTINCT_BY_FIELDS = ['nodeId', 'mac'];

const comparer = field => (a, b) => (a[field] < b[field] ? -1 : 1);
const distinctFieldsComparer = fields => (x, y) => fields.every(field => x[field] === y[field]);

source
  .pipe(
    groupBy(metric => metric[GROUP_BY]),
    mergeMap(group =>
      group.pipe(
        bufferCount(BUFFER_SIZE, 1),
        mergeMap(metric => from(metric).pipe(max(comparer(COMPARE_KEY)))),
        distinctUntilChanged(distinctFieldsComparer(DISTINCT_BY_FIELDS))
      )
    )
  )
  .subscribe(e => {
    console.log(e);
  });

您当前的代码很接近,事实上我可以重用大部分代码。

出问题的是 group.pipe(toArray()) 只会在组完成时发出(并且只有在源完成时才会发生)。你想要做的是获得一个滑动window。您可以使用 bufferCount(BUFFER_SIZE, 1) 这样做。它会每 1 个项目发出最后 3 个项目,因此允许您在组每次获得新项目时检查最后 3 个项目。

const GROUP_BY = 'mac';
const DISTINCT_BY = 'nodeId';
const COMPARE_KEY = 'rssi';
const distinctComparer = field => (x, y) => x[field] === y[field];
const BUFFER_SIZE = 3;
const comparer = field => (a, b) => (a[field] < b[field] ? -1 : 1);

source.pipe(
    groupBy(metric => metric[GROUP_BY])
    mergeMap(grp => grp.pipe(
      bufferCount(BUFFER_SIZE, 1)),
      mergeMap(metric => from(metric).pipe(max(comparer(COMPARE_KEY))))
      distinctUntilChanged(distinctComparer(DISTINCT_BY))
    )  
  )

此外,我认为您想比较并获得小组中的最大值。为此,您需要将所有内容放入处理各个组的 mergeMap 中。