|
1345 | 1345 | for (let i = 0; i < deviceCount; i++) { |
1346 | 1346 | const cell = self.configFrame().Cells[i]; |
1347 | 1347 |
|
| 1348 | + // For an existing device the lat/long loaded from the database via queryDeviceByID is |
| 1349 | + // authoritative; do not let the (possibly stale, or parent-derived) coordinates carried in the |
| 1350 | + // config frame / auto-saved JSON mapping overwrite it. Only seed the screen-level lat/long from |
| 1351 | + // cell values when defining a new device (fresh analyze / config import). |
1348 | 1352 | // TODO: Update screen to accommodate lat/long at the device level |
1349 | | - if (!isEmpty(cell.Latitude)) |
1350 | | - self.latitude(cell.Latitude); |
| 1353 | + if (deviceID === 0) { |
| 1354 | + if (!isEmpty(cell.Latitude)) |
| 1355 | + self.latitude(cell.Latitude); |
1351 | 1356 |
|
1352 | | - if (!isEmpty(cell.Longitude)) |
1353 | | - self.longitude(cell.Longitude); |
| 1357 | + if (!isEmpty(cell.Longitude)) |
| 1358 | + self.longitude(cell.Longitude); |
| 1359 | + } |
1354 | 1360 |
|
1355 | 1361 | let cellAcronym = cell.IDLabel; |
1356 | 1362 |
|
|
2633 | 2639 | if (!nextVoltage) |
2634 | 2640 | continue; |
2635 | 2641 |
|
| 2642 | + // See if this line current has already been matched |
| 2643 | + if (lineCurrentExists(lines, nextCurrent)) |
| 2644 | + continue; |
| 2645 | +
|
2636 | 2646 | // See if this next current is for matching line based on label minus phase designations |
2637 | 2647 | if (match === nextCurrent.Label().trim().toUpperCase().replace(/[ABCRYB]/gi, "")) { |
2638 | 2648 | line[nextPhase] = { |
|
3628 | 3638 | device.AccessID = cell.IDCode; |
3629 | 3639 | device.Acronym = cell.IDLabel(); |
3630 | 3640 |
|
| 3641 | + // Save lat/long for child devices: prefer the cell's own coordinates when present, |
| 3642 | + // otherwise fall back to the on-screen value - matches parent / direct-connected device |
| 3643 | + // behavior. A zero or null coordinate is treated as "unset" by isEmpty, consistent with |
| 3644 | + // the load-time logic that pushes cell coordinates onto the screen. |
| 3645 | + device.Longitude = isEmpty(cell.Longitude) ? viewModel.longitude() : cell.Longitude; |
| 3646 | + device.Latitude = isEmpty(cell.Latitude) ? viewModel.latitude() : cell.Latitude; |
| 3647 | +
|
3631 | 3648 | if (isEmpty(device.Name)) |
3632 | 3649 | device.Name = device.Acronym; |
3633 | 3650 |
|
|
3766 | 3783 | device.ProtocolID = configFrame.ProtocolID; |
3767 | 3784 | device.FrameRate = configFrame.FrameRate; |
3768 | 3785 | device.AccessID = configFrame.IDCode; |
3769 | | - device.IsConcentrator = !isEmpty(connectionString) && (configFrame.IsConcentrator || configFrame.Cells.length > 1); |
3770 | 3786 |
|
3771 | 3787 | if (isEmpty(device.Name)) |
3772 | 3788 | device.Name = device.Acronym; |
3773 | 3789 |
|
3774 | | - // Only update connection string if one has been defined, prevents changing any existing one to blank |
3775 | | - if (connectionString.length > 0) |
| 3790 | + // Only update connection string and concentrator flag when a connection string has been defined. |
| 3791 | + // This prevents changing any existing connection string to blank and, just as importantly, prevents |
| 3792 | + // clearing the concentrator flag on an existing PDC when it is re-saved from an auto-loaded JSON config |
| 3793 | + // that does not carry a connection string (see connection string preservation for auto-JSON config I/O). |
| 3794 | + if (connectionString.length > 0) { |
3776 | 3795 | device.ConnectionString = connectionString; |
| 3796 | + device.IsConcentrator = configFrame.IsConcentrator || configFrame.Cells.length > 1; |
| 3797 | + } |
3777 | 3798 |
|
3778 | 3799 | device.AutoStartDataParsingSequence = autoStartDataParsingSequence; |
3779 | 3800 | device.SkipDisableRealTimeData = skipDisableRealTimeData; |
|
0 commit comments