Skip to content

Commit 26cffc5

Browse files
authored
Changes in the mapping agent to map the extra unknown discovered devices to devices in the site model (#1128)
* Handling spurious log for last start updates when the last start is not changed * updating comment style * changes from master * Revert "changes from master" This reverts commit d53c53b. * changes in the mapping agent to map the extra unknown discovered devices to devices in the site model * changing the map command only and not the filename used earlier * changing the file name for map command * changing the file name for map command * file name to be used for the new device discovered * changes to address review comments * changes to address review comments * changes to address review comments * changes to address review comments * changes to address review comments * update in test/automapper to call the mapping command * fixing unit tests failure * using automapper to start mapping and test the process * using automapper to start mapping and test the process * addressing review comments
1 parent 0d1b9eb commit 26cffc5

File tree

5 files changed

+145
-20
lines changed

5 files changed

+145
-20
lines changed

bin/test_automapper

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,36 @@ echo Checking discovered device metadata
5959
addr=$(jq -r .addr $site_path/extras/discovered_vendor-20231/cloud_metadata/udmi_discovered_with.json)
6060
[[ $addr == 20231 ]] || fail Vendor device addr should be 20231, was $addr
6161

62+
echo "Changing the address for AHU-22 device to 0x68"
63+
device_metadata=$site_path/devices/AHU-22/metadata.json
64+
jq '.localnet.families.vendor.addr = "0x68"' $device_metadata | sponge $device_metadata
65+
66+
echo "Starting the mapping process for the extra devices"
67+
bin/mapper GAT-123 map
68+
69+
[[ -f $site_path/devices/UNK-1/metadata.json ]] || fail "Terminating because of extra device which does not exist didn't map correctly."
70+
71+
echo Checking address of new mapped device
72+
addr=$(jq -r .localnet.families.vendor.addr $site_path/devices/UNK-1/metadata.json )
73+
[[ $addr == 0x65 ]] || fail Vendor device addr should be 0x65, was $addr
74+
75+
echo "Reverting the address for AHU-22 device back"
76+
device_metadata=$site_path/devices/AHU-22/metadata.json
77+
jq '.localnet.families.vendor.addr = "0x65"' $device_metadata | sponge $device_metadata
78+
79+
80+
if [[ -d $site_path/devices/UNK-1 ]]; then
81+
echo "Directory '$site_path/devices/UNK-1' exists. Removing it..."
82+
if rm -r "$site_path/devices/UNK-1"; then
83+
echo "Directory '$site_path/devices/UNK-1' removed successfully."
84+
else
85+
echo "Error: Failed to remove '$site_path/devices/UNK-1'."
86+
exit 1
87+
fi
88+
else
89+
echo "Directory '$site_path/devices/UNK-1' does not exist. Nothing to remove."
90+
fi
91+
6292
first_generation=`jq -r .generation $site_path/extras/discovered_vendor-20231/cloud_metadata/udmi_discovered_with.json`
6393
echo First discovered generation is $first_generation
6494

common/src/main/java/com/google/udmi/util/Common.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import java.util.ArrayList;
1414
import java.util.List;
1515
import java.util.MissingFormatArgumentException;
16+
import java.util.Objects;
1617
import java.util.Optional;
1718
import java.util.Set;
1819
import java.util.TreeSet;
@@ -71,6 +72,10 @@ public abstract class Common {
7172
public static final int EXIT_CODE_ERROR = 1;
7273
public static final String UNKNOWN_UDMI_VERSION = "unknown";
7374

75+
public static final String UNKNOWN_DEVICE_ID_PREFIX = "UNK-";
76+
77+
public static final String DOUBLE_COLON_SEPARATOR = "::";
78+
7479
/**
7580
* Remove the next item from the list in an exception-safe way.
7681
*/
@@ -208,4 +213,10 @@ public static void forcedDelayedShutdown() {
208213
safeSleep(2000);
209214
System.exit(0);
210215
}
216+
217+
public static String generateColonKey(String field1, String field2) {
218+
Objects.requireNonNull(field1, "field1 cannot be null");
219+
Objects.requireNonNull(field2, "field2 cannot be null");
220+
return field1 + DOUBLE_COLON_SEPARATOR + field2;
221+
}
211222
}

common/src/main/java/com/google/udmi/util/SiteModel.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,13 @@ public boolean getStrictWarnings() {
629629
return isTrue(siteMetadata.strict_warnings);
630630
}
631631

632+
public void createNewDevice(String deviceId, Metadata metadata) {
633+
File metadataFile = getDeviceFile(deviceId, METADATA_JSON);
634+
System.err.println("Writing device metadata file " + metadataFile);
635+
metadataFile.getParentFile().mkdirs();
636+
JsonUtil.writeFile(metadata, metadataFile);
637+
}
638+
632639
public static class MetadataException extends Metadata {
633640

634641
public final File file;

validator/.idea/runConfigurations/MappingAgent_Reconcile.xml renamed to validator/.idea/runConfigurations/MappingAgent_Map.xml

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

validator/src/main/java/com/google/daq/mqtt/mapping/MappingAgent.java

Lines changed: 95 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
import static com.google.common.base.Preconditions.checkNotNull;
44
import static com.google.common.base.Preconditions.checkState;
55
import static com.google.daq.mqtt.util.ConfigUtil.UDMI_VERSION;
6+
import static com.google.udmi.util.Common.UNKNOWN_DEVICE_ID_PREFIX;
7+
import static com.google.udmi.util.Common.generateColonKey;
68
import static com.google.udmi.util.Common.removeNextArg;
79
import static com.google.udmi.util.GeneralUtils.catchToNull;
810
import static com.google.udmi.util.JsonUtil.isoConvert;
@@ -21,7 +23,6 @@
2123
import com.google.daq.mqtt.util.CloudIotManager;
2224
import com.google.daq.mqtt.util.ConfigUtil;
2325
import com.google.udmi.util.Common;
24-
import com.google.udmi.util.JsonUtil;
2526
import com.google.udmi.util.SiteModel;
2627
import java.io.File;
2728
import java.util.ArrayList;
@@ -33,6 +34,7 @@
3334
import java.util.Map;
3435
import java.util.Map.Entry;
3536
import java.util.Set;
37+
import java.util.concurrent.atomic.AtomicInteger;
3638
import udmi.schema.CloudModel;
3739
import udmi.schema.CloudModel.ModelOperation;
3840
import udmi.schema.DiscoveryConfig;
@@ -41,7 +43,9 @@
4143
import udmi.schema.Envelope.SubFolder;
4244
import udmi.schema.ExecutionConfiguration;
4345
import udmi.schema.FamilyDiscoveryConfig;
46+
import udmi.schema.FamilyLocalnetModel;
4447
import udmi.schema.GatewayModel;
48+
import udmi.schema.LocalnetModel;
4549
import udmi.schema.Metadata;
4650
import udmi.schema.SystemModel;
4751

@@ -60,6 +64,8 @@ public class MappingAgent {
6064
private SiteModel siteModel;
6165
private Date generationDate;
6266

67+
private AtomicInteger suffixToStart = new AtomicInteger(1);
68+
6369
/**
6470
* Create an agent given the configuration.
6571
*/
@@ -98,7 +104,7 @@ void process(List<String> argsList) {
98104
switch (mappingCommand) {
99105
case "provision" -> setupProvision();
100106
case "discover" -> initiateDiscover();
101-
case "reconcile" -> reconcileDiscovery();
107+
case "map" -> mapDiscoveredDevices();
102108
default -> throw new RuntimeException("Unknown mapping command " + mappingCommand);
103109
}
104110
System.err.printf("Completed mapper %s command%n", mappingCommand);
@@ -141,26 +147,83 @@ private FamilyDiscoveryConfig getFamilyDiscoveryConfig(String family) {
141147
return familyDiscoveryConfig;
142148
}
143149

144-
private void reconcileDiscovery() {
150+
private void mapDiscoveredDevices() {
151+
List<Entry<String, Metadata>> mappedDiscoveredEntries = getMappedDiscoveredEntries();
152+
Map<String, Metadata> devicesEntriesMap = getDevicesEntries();
153+
Map<String, String> devicesFamilyAddressMap = getDeviceFamilyAddressMap();
154+
155+
Set<String> devicesPresent = new HashSet<>();
156+
mappedDiscoveredEntries.forEach(entry -> {
157+
158+
if (devicesEntriesMap.containsKey(entry.getKey())) {
159+
System.err.println("Skipping existing device file for family::address = " + entry.getKey());
160+
devicesPresent.add(devicesFamilyAddressMap.get(entry.getKey()));
161+
//TODO: update the existing device
162+
} else {
163+
String newDeviceId = getNextDeviceId();
164+
while (devicesPresent.contains(newDeviceId)) {
165+
newDeviceId = getNextDeviceId();
166+
}
167+
devicesPresent.add(newDeviceId);
168+
siteModel.createNewDevice(newDeviceId, entry.getValue());
169+
}
170+
});
171+
172+
updateProxyIdsForDiscoveryNode(devicesPresent);
173+
}
174+
175+
private Map<String, String> getDeviceFamilyAddressMap() {
176+
Map<String, String> devicesFamilyAddressMap = new HashMap<>();
177+
178+
for (String device : siteModel.allMetadata().keySet()) {
179+
Metadata deviceMetadata = siteModel.allMetadata().get(device);
180+
if (deviceMetadata.localnet == null || deviceMetadata.localnet.families == null) {
181+
continue;
182+
}
183+
Map<String, FamilyLocalnetModel> deviceFamilies = deviceMetadata.localnet.families;
184+
for (String familyName : deviceFamilies.keySet()) {
185+
devicesFamilyAddressMap.put(generateColonKey(familyName,
186+
deviceFamilies.get(familyName).addr), device);
187+
}
188+
}
189+
190+
return devicesFamilyAddressMap;
191+
}
192+
193+
private String getNextDeviceId() {
194+
return UNKNOWN_DEVICE_ID_PREFIX + suffixToStart.getAndIncrement();
195+
}
196+
197+
private List<Entry<String, Metadata>> getMappedDiscoveredEntries() {
145198
File extrasDir = siteModel.getExtrasDir();
146199
File[] extras = extrasDir.listFiles();
147200
if (extras == null || extras.length == 0) {
148201
throw new RuntimeException("No extras found to reconcile");
149202
}
150-
List<Entry<String, Metadata>> entries = Arrays.stream(extras).map(this::convertExtra)
203+
List<Entry<String, Metadata>> mappedDiscoveredEntries = Arrays.stream(extras)
204+
.map(this::convertExtraDiscoveredEvents)
151205
.filter(entry -> !entry.getKey().equals(NO_DISCOVERY)).toList();
152-
entries.forEach(entry -> {
153-
File metadataFile = siteModel.getDeviceFile(entry.getKey(), METADATA_JSON);
154-
if (metadataFile.exists()) {
155-
System.err.println("Skipping existing device file " + metadataFile);
156-
} else {
157-
System.err.println("Writing device metadata file " + metadataFile);
158-
metadataFile.getParentFile().mkdirs();
159-
JsonUtil.writeFile(entry.getValue(), metadataFile);
206+
return mappedDiscoveredEntries;
207+
}
208+
209+
private Map<String, Metadata> getDevicesEntries() {
210+
Map<String, Metadata> devicesEntriesMap = new HashMap<>();
211+
212+
for (Metadata deviceMetadata : siteModel.allMetadata().values()) {
213+
if (deviceMetadata.localnet == null || deviceMetadata.localnet.families == null) {
214+
continue;
160215
}
161-
});
216+
Map<String, FamilyLocalnetModel> deviceFamilies = deviceMetadata.localnet.families;
217+
for (String familyName : deviceFamilies.keySet()) {
218+
devicesEntriesMap.put(generateColonKey(familyName,
219+
deviceFamilies.get(familyName).addr), deviceMetadata);
220+
}
221+
}
222+
223+
return devicesEntriesMap;
224+
}
162225

163-
List<String> proxyIds = entries.stream().map(Entry::getKey).toList();
226+
private void updateProxyIdsForDiscoveryNode(Set<String> proxyIds) {
164227
File gatewayMetadata = siteModel.getDeviceFile(deviceId, METADATA_JSON);
165228
Metadata metadata = loadFileStrictRequired(Metadata.class, gatewayMetadata);
166229
List<String> idList = ofNullable(metadata.gateway.proxy_ids).orElse(ImmutableList.of());
@@ -173,20 +236,34 @@ private void reconcileDiscovery() {
173236
writeFile(metadata, gatewayMetadata);
174237
}
175238

176-
private Entry<String, Metadata> convertExtra(File file) {
239+
private Entry<String, Metadata> convertExtraDiscoveredEvents(File file) {
177240
DiscoveryEvents discoveryEvents = loadFileStrict(DiscoveryEvents.class,
178241
new File(file, "cloud_metadata/udmi_discovered_with.json"));
179-
if (discoveryEvents == null) {
242+
boolean isInvalidDiscoveryEvent = false;
243+
if (discoveryEvents.family == null || discoveryEvents.addr == null) {
244+
System.err.println("Invalid discovery event, family or address not present");
245+
isInvalidDiscoveryEvent = true;
246+
}
247+
if (discoveryEvents == null || isInvalidDiscoveryEvent) {
180248
return Map.entry(NO_DISCOVERY, new Metadata());
181249
}
182250
Metadata metadata = new Metadata();
183251
metadata.version = UDMI_VERSION;
184252
metadata.timestamp = new Date();
185253
metadata.system = new SystemModel();
186254
metadata.gateway = new GatewayModel();
255+
populateMetadataLocalnet(discoveryEvents, metadata);
187256
metadata.gateway.gateway_id = deviceId;
188-
String deviceName = (String) discoveryEvents.system.ancillary.get("device-name");
189-
return Map.entry(deviceName, metadata);
257+
return Map.entry(generateColonKey(discoveryEvents.family,
258+
discoveryEvents.addr), metadata);
259+
}
260+
261+
private static void populateMetadataLocalnet(DiscoveryEvents discoveryEvents, Metadata metadata) {
262+
metadata.localnet = new LocalnetModel();
263+
metadata.localnet.families = new HashMap<>();
264+
FamilyLocalnetModel familyLocalnetModel = new FamilyLocalnetModel();
265+
familyLocalnetModel.addr = discoveryEvents.addr;
266+
metadata.localnet.families.put(discoveryEvents.family, familyLocalnetModel);
190267
}
191268

192269
private void initialize() {

0 commit comments

Comments
 (0)