Skip to content

Commit

Permalink
Remove create edge function (#1937)
Browse files Browse the repository at this point in the history
* Remove create edge function

Co-authored-by: Mikhail Chatillon <chmikhai@microsoft.com>
  • Loading branch information
fbeltrao and Mandur authored Oct 28, 2022
1 parent f44e93d commit 1d1202c
Show file tree
Hide file tree
Showing 56 changed files with 598 additions and 798 deletions.
10 changes: 10 additions & 0 deletions .github/workflows/ci.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,15 @@ jobs:
/p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:ExcludeByFile="**/${{ env.TESTS_FOLDER }}/" \
${{ env.TESTS_FOLDER }}/Integration/LoRaWan.Tests.Integration.csproj
# Run cli tests
- name: Run cli unit tests
run: |
dotnet test --configuration ${{ env.buildConfiguration }} \
--logger trx -r ${{ env.TESTS_RESULTS_FOLDER }}/Cli.Unit \
/p:CollectCoverage=true /p:CoverletOutputFormat=cobertura /p:ExcludeByFile="**/${{ env.TESTS_FOLDER }}/" \
./Tools/Cli-LoRa-Device-Provisioning/Tests/LoRaWan.Tools.CLI.Tests.Unit/LoRaWan.Tools.CLI.Tests.Unit.csproj
# Upload test results as artifact
- uses: actions/upload-artifact@v3
if: success() || failure()
Expand All @@ -88,6 +97,7 @@ jobs:
path: |
${{ env.TESTS_RESULTS_FOLDER }}/Unit
${{ env.TESTS_RESULTS_FOLDER }}/Integration
${{ env.TESTS_RESULTS_FOLDER }}/Cli.Unit
- name: Upload to Codecov test reports
uses: codecov/codecov-action@v3
Expand Down
1 change: 1 addition & 0 deletions AssemblyInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,5 @@
[assembly: InternalsVisibleTo("LoRaWan.Tests.E2E")]
[assembly: InternalsVisibleTo("LoRaWan.Tests.Common")]
[assembly: InternalsVisibleTo("LoRaWan.Tests.Simulation")]
[assembly: InternalsVisibleTo("LoRaWan.Tools.CLI.Tests.Unit")]
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
107 changes: 0 additions & 107 deletions LoRaEngine/LoraKeysManagerFacade/CreateEdgeDevice.cs

This file was deleted.

1 change: 0 additions & 1 deletion LoRaEngine/LoraKeysManagerFacade/FacadeStartup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,6 @@ public override void Configure(IFunctionsHostBuilder builder)
deviceCacheStore,
sp.GetRequiredService<ILoggerFactory>(),
sp.GetRequiredService<ILogger<LoRaADRServerManager>>()))
.AddSingleton<CreateEdgeDevice>()
.AddSingleton<IChannelPublisher>(sp => new RedisChannelPublisher(redis, sp.GetRequiredService<ILogger<RedisChannelPublisher>>()))
.AddSingleton<DeviceGetter>()
.AddSingleton<IEdgeDeviceGetter, EdgeDeviceGetter>()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,5 @@ public interface IDeviceRegistryManager
IRegistryPageResult<ILoRaDeviceTwin> FindDeviceByDevEUI(DevEui devEUI);
Task<IDeviceTwin> UpdateTwinAsync(string deviceName, IDeviceTwin twin, string eTag);
Task RemoveDeviceAsync(string deviceId);
Task DeployEdgeDeviceAsync(
string deviceId,
string resetPin,
string spiSpeed,
string spiDev,
string publishingUserName,
string publishingPassword,
string networkId = Constants.NetworkId,
string lnsHostAddress = "ws://mylns:5000");
Task DeployConcentratorAsync(string stationEuiString, string region, string networkId = Constants.NetworkId);
Task<bool> DeployEndDevicesAsync();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -113,133 +113,5 @@ public async Task<ILoRaDeviceTwin> GetLoRaDeviceTwinAsync(string deviceId, Cance

public async Task<IDeviceTwin> GetTwinAsync(string deviceId, CancellationToken? cancellationToken = null)
=> await this.instance.GetTwinAsync(deviceId, cancellationToken ?? CancellationToken.None) is { } twin ? new IoTHubDeviceTwin(twin) : null;

public async Task DeployEdgeDeviceAsync(
string deviceId,
string resetPin,
string spiSpeed,
string spiDev,
string publishingUserName,
string publishingPassword,
string networkId = Constants.NetworkId,
string lnsHostAddress = "ws://mylns:5000")
{
// Get function facade key
var base64Auth = Convert.ToBase64String(Encoding.Default.GetBytes($"{publishingUserName}:{publishingPassword}"));
var apiUrl = new Uri($"https://{Environment.GetEnvironmentVariable("WEBSITE_CONTENTSHARE")}.scm.azurewebsites.net");
var siteUrl = new Uri($"https://{Environment.GetEnvironmentVariable("WEBSITE_CONTENTSHARE")}.azurewebsites.net");
string jwt;
using (var client = this.httpClientFactory.CreateClient())
{
client.DefaultRequestHeaders.Add("Authorization", $"Basic {base64Auth}");
var result = await client.GetAsync(new Uri(apiUrl, "/api/functions/admin/token"));
jwt = (await result.Content.ReadAsStringAsync()).Trim('"'); // get JWT for call funtion key
}

var facadeKey = string.Empty;
using (var client = this.httpClientFactory.CreateClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + jwt);
var response = await client.GetAsync(new Uri(siteUrl, "/admin/host/keys"));
var jsonResult = await response.Content.ReadAsStringAsync();
dynamic resObject = JsonConvert.DeserializeObject(jsonResult);
facadeKey = resObject.keys[0].value;
}

var edgeGatewayDevice = new Device(deviceId)
{
Capabilities = new DeviceCapabilities()
{
IotEdge = true
}
};

_ = await this.instance.AddDeviceAsync(edgeGatewayDevice);
_ = await this.instance.AddModuleAsync(new Module(deviceId, "LoRaWanNetworkSrvModule"));

async Task<ConfigurationContent> GetConfigurationContentAsync(Uri configLocation, IDictionary<string, string> tokenReplacements)
{
using var httpClient = this.httpClientFactory.CreateClient();
var json = await httpClient.GetStringAsync(configLocation);
foreach (var r in tokenReplacements)
json = json.Replace(r.Key, r.Value, StringComparison.Ordinal);
return JsonConvert.DeserializeObject<ConfigurationContent>(json);
}

var deviceConfigurationContent = await GetConfigurationContentAsync(new Uri(Environment.GetEnvironmentVariable("DEVICE_CONFIG_LOCATION")), new Dictionary<string, string>
{
["[$reset_pin]"] = resetPin,
["[$spi_speed]"] = string.IsNullOrEmpty(spiSpeed) || string.Equals(spiSpeed, "8", StringComparison.OrdinalIgnoreCase) ? string.Empty : ",'SPI_SPEED':{'value':'2'}",
["[$spi_dev]"] = string.IsNullOrEmpty(spiDev) || string.Equals(spiDev, "0", StringComparison.OrdinalIgnoreCase) ? string.Empty : $",'SPI_DEV':{{'value':'{spiDev}'}}"
});

await this.instance.ApplyConfigurationContentOnDeviceAsync(deviceId, deviceConfigurationContent);

if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("LOG_ANALYTICS_WORKSPACE_ID")))
{
this.logger.LogDebug("Opted-in to use Azure Monitor on the edge. Deploying the observability layer.");
// If Appinsights Key is set this means that user opted in to use Azure Monitor.
_ = await this.instance.AddModuleAsync(new Module(deviceId, "IotHubMetricsCollectorModule"));
var observabilityConfigurationContent = await GetConfigurationContentAsync(new Uri(Environment.GetEnvironmentVariable("OBSERVABILITY_CONFIG_LOCATION")), new Dictionary<string, string>
{
["[$iot_hub_resource_id]"] = Environment.GetEnvironmentVariable("IOT_HUB_RESOURCE_ID"),
["[$log_analytics_workspace_id]"] = Environment.GetEnvironmentVariable("LOG_ANALYTICS_WORKSPACE_ID"),
["[$log_analytics_shared_key]"] = Environment.GetEnvironmentVariable("LOG_ANALYTICS_WORKSPACE_KEY")
});

_ = await this.instance.AddConfigurationAsync(new Configuration($"obs-{Guid.NewGuid()}")
{
Content = observabilityConfigurationContent,
TargetCondition = $"deviceId='{deviceId}'"
});
}

var twin = new Twin();
twin.Properties.Desired = new TwinCollection($"{{FacadeServerUrl:'https://{Environment.GetEnvironmentVariable("FACADE_HOST_NAME", EnvironmentVariableTarget.Process)}.azurewebsites.net/api/',FacadeAuthCode: '{facadeKey}'}}");
twin.Properties.Desired["hostAddress"] = new Uri(lnsHostAddress);
twin.Tags[Constants.NetworkTagName] = networkId;
var remoteTwin = await this.instance.GetTwinAsync(deviceId);

_ = await this.instance.UpdateTwinAsync(deviceId, "LoRaWanNetworkSrvModule", twin, remoteTwin.ETag);
}

public async Task DeployConcentratorAsync(string stationEuiString, string region, string networkId = Constants.NetworkId)
{
// Deploy concentrator
using var httpClient = this.httpClientFactory.CreateClient();
var regionalConfiguration = region switch
{
var s when string.Equals("EU", s, StringComparison.OrdinalIgnoreCase) => await httpClient.GetStringAsync(new Uri(Environment.GetEnvironmentVariable("EU863_CONFIG_LOCATION", EnvironmentVariableTarget.Process))),
var s when string.Equals("US", s, StringComparison.OrdinalIgnoreCase) => await httpClient.GetStringAsync(new Uri(Environment.GetEnvironmentVariable("US902_CONFIG_LOCATION", EnvironmentVariableTarget.Process))),
_ => throw new SwitchExpressionException("Region should be either 'EU' or 'US'")
};

var concentratorDevice = new Device(stationEuiString);
_ = await this.instance.AddDeviceAsync(concentratorDevice);
var concentratorTwin = await this.instance.GetTwinAsync(stationEuiString);
concentratorTwin.Properties.Desired["routerConfig"] = JsonConvert.DeserializeObject<JObject>(regionalConfiguration);
concentratorTwin.Tags[Constants.NetworkTagName] = networkId;
_ = await this.instance.UpdateTwinAsync(stationEuiString, concentratorTwin, concentratorTwin.ETag);
}

public async Task<bool> DeployEndDevicesAsync()
{
var otaaDevice = await this.instance.GetDeviceAsync(Constants.OtaaDeviceId)
?? await this.instance.AddDeviceAsync(new Device(Constants.OtaaDeviceId));

var otaaEndTwin = new Twin();
otaaEndTwin.Properties.Desired = new TwinCollection(/*lang=json*/ @"{AppEUI:'BE7A0000000014E2',AppKey:'8AFE71A145B253E49C3031AD068277A1',GatewayID:'',SensorDecoder:'DecoderValueSensor'}");
var otaaRemoteTwin = _ = await this.instance.GetTwinAsync(Constants.OtaaDeviceId);
_ = await this.instance.UpdateTwinAsync(Constants.OtaaDeviceId, otaaEndTwin, otaaRemoteTwin.ETag);

var abpDevice = await this.instance.GetDeviceAsync(Constants.AbpDeviceId)
?? await this.instance.AddDeviceAsync(new Device(Constants.AbpDeviceId));
var abpTwin = new Twin();
abpTwin.Properties.Desired = new TwinCollection(/*lang=json*/ @"{AppSKey:'2B7E151628AED2A6ABF7158809CF4F3C',NwkSKey:'3B7E151628AED2A6ABF7158809CF4F3C',GatewayID:'',DevAddr:'0228B1B1',SensorDecoder:'DecoderValueSensor'}");
var abpRemoteTwin = await this.instance.GetTwinAsync(Constants.AbpDeviceId);
_ = await this.instance.UpdateTwinAsync(Constants.AbpDeviceId, abpTwin, abpRemoteTwin.ETag);

return abpDevice != null && otaaDevice != null;
}
}
}
4 changes: 2 additions & 2 deletions TemplateBicep/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,13 @@ For device creation debugging, there are alternatives other than deploying the w
Option 1: Run bash script locally

```plain
FACADE_SERVER_URL="https://myapp.com/api" IOTHUB_CONNECTION_STRING="<iothub-connection-string>" LORA_CLI_URL="https://github.com/Azure/iotedge-lorawan-starterkit/releases/download/v2.2.0/lora-cli.linux-x64.tar.gz" EDGE_GATEWAY_NAME="<iotedge-device-name>" STATION_DEVICE_NAME="<concentrator-device-name>" DEPLOY_DEVICE=1 RESET_PIN=<concentrator-reset-pin> ./create_device.sh
FACADE_SERVER_URL="https://myapp.com/api" IOTHUB_CONNECTION_STRING="<iothub-connection-string>" LORA_CLI_URL="https://github.com/Azure/iotedge-lorawan-starterkit/releases/download/v2.2.0/lora-cli.linux-x64.tar.gz" EDGE_GATEWAY_NAME="<iotedge-device-name>" STATION_DEVICE_NAME="<concentrator-device-name>" DEPLOY_DEVICE=1 RESET_PIN=<concentrator-reset-pin> LORA_VERSION="<lora-starter-kit-release-version>" ./create_device.sh
```

Option 2: Run the device provisioning Bicep

```plain
az deployment group create --resource-group <resource-group-name> --template-file ./devices.bicep --parameters iothubName="<unique-name>"
resetPin=<based-on-your-setup> edgeGatewayName="<gateway-device-name>" spiSpeed=<based-on-your-setup> spiDev=<based-on-your-setup> functionAppName="<function-name>" region="<lora-region>" stationEui="<concentrator-device-name>" logAnalyticsName="<log-analytics-name>"
loraCliUrl="<lora-cli-linux-musl-version-download-url>" deployDevice=true
loraCliUrl="<lora-cli-linux-musl-version-download-url>" version="<lora-starter-kit-release-version>" deployDevice=true
```
2 changes: 1 addition & 1 deletion TemplateBicep/create_device.sh
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ create_devices_with_lora_cli() {
fi

echo "Creating gateway $EDGE_GATEWAY_NAME..."
./loradeviceprovisioning add-gateway --reset-pin "$RESET_PIN" --device-id "$EDGE_GATEWAY_NAME" --spi-dev "$SPI_DEV" --spi-speed "$SPI_SPEED" --api-url "$FACADE_SERVER_URL" --api-key "$FACADE_AUTH_CODE" --lns-host-address "$LNS_HOST_ADDRESS" --network "$NETWORK" --monitoring "$monitoringEnabled" --iothub-resource-id "$IOTHUB_RESOURCE_ID" --log-analytics-workspace-id "$LOG_ANALYTICS_WORKSPACE_ID" --log-analytics-shared-key "$LOG_ANALYTICS_SHARED_KEY"
./loradeviceprovisioning add-gateway --reset-pin "$RESET_PIN" --device-id "$EDGE_GATEWAY_NAME" --spi-dev "$SPI_DEV" --spi-speed "$SPI_SPEED" --api-url "$FACADE_SERVER_URL" --api-key "$FACADE_AUTH_CODE" --lns-host-address "$LNS_HOST_ADDRESS" --network "$NETWORK" --monitoring "$monitoringEnabled" --iothub-resource-id "$IOTHUB_RESOURCE_ID" --log-analytics-workspace-id "$LOG_ANALYTICS_WORKSPACE_ID" --log-analytics-shared-key "$LOG_ANALYTICS_SHARED_KEY" --lora-version "$LORA_VERSION"

echo "Creating concentrator $STATION_DEVICE_NAME for region $regionName..."
./loradeviceprovisioning add --type concentrator --region "$regionName" --stationeui "$STATION_DEVICE_NAME" --no-cups --network "$NETWORK"
Expand Down
11 changes: 8 additions & 3 deletions TemplateBicep/devices.bicep
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
param location string = resourceGroup().location
param iothubName string = ''
param edgeGatewayName string = ''
param iothubName string
param edgeGatewayName string
param resetPin int
param spiSpeed int
param spiDev int
param utcValue string = utcNow()
param functionAppName string = ''
param functionAppName string
param region string
param stationEui string
param lnsHostAddress string = 'ws://mylns:5000'
param useAzureMonitorOnEdge bool = true
param logAnalyticsName string
param deployDevice bool
param loraCliUrl string
param version string

resource iotHub 'Microsoft.Devices/IotHubs@2021-07-02' existing = {
name: iothubName
Expand Down Expand Up @@ -106,6 +107,10 @@ resource createIothubDevices 'Microsoft.Resources/deploymentScripts@2020-10-01'
name: 'LORA_CLI_URL'
value: loraCliUrl
}
{
name: 'LORA_VERSION'
value: version
}
]
scriptContent: loadTextContent('./create_device.sh')
}
Expand Down
Loading

0 comments on commit 1d1202c

Please sign in to comment.