Skip to content

Commit 2843c83

Browse files
authored
Merge pull request #14 from oracle-devrel/iotgateway
Iotgateway
2 parents 1d36e46 + 22fc9f4 commit 2843c83

60 files changed

Lines changed: 5394 additions & 0 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

IotDemoGateway/.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
/.factorypath
2+
/.project
3+
/target/
4+
/.settings/
5+
/.classpath
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
[
2+
{
3+
"condition": "*",
4+
"description": "Default condition",
5+
"payload-mapping": {
6+
"$.CurrentChargePercentage": "$.currentBatteryCapacityPercentage",
7+
"$.OperatingMode": "${if (.operatingMode == 1) then \"Manual\" elif (.operatingMode == 2) then \"Automatic - Self-Consumption\" elif (.operatingMode == 6) then \"Battery-Module-Extension (30%)\" elif (.operatingMode == 10) then \"Time-Of-Use\" else \"Unknown Mode\" end}",
8+
"$.ReservedChargePercentage": "$.reservedBatteryCapacityPercentage",
9+
"$.comment": "$.comment",
10+
"$.StatusTimestamp": "$.timestamp"
11+
},
12+
"reference-payload": {
13+
"dataFormat": "JSON",
14+
"data": {
15+
"currentBatteryCapacityPercentage": 59,
16+
"operatingMode": 2,
17+
"reservedBatteryCapacityPercentage": 5,
18+
"comment": "Your comment on the update",
19+
"time": 1763981430279,
20+
"timestamp": "2025-11-24T10:50:30.279369Z"
21+
}
22+
}
23+
}
24+
]
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
{
2+
"reference-endpoint": "house/sonnen/status",
3+
"reference-payload": {
4+
"data": {
5+
"currentBatteryCapacityPercentage": 0,
6+
"operatingMode": 0,
7+
"reservedBatteryCapacityPercentage": 0,
8+
"time": 123456,
9+
"comment": "Your random comment",
10+
"timestamp": "2025-11-18T16:23:52.081763412Z"
11+
},
12+
"data-format": "JSON"
13+
},
14+
"envelope-mapping": {
15+
"timeObserved": "$.time"
16+
}
17+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
{
2+
"@context": [
3+
"dtmi:dtdl:context;3",
4+
"dtmi:dtdl:extension:historization;1",
5+
"dtmi:dtdl:extension:quantitativeTypes;1",
6+
"dtmi:com:oracle:dtdl:extension:validation;1"
7+
],
8+
"@id": "dtmi:com:oracle:demo:timg:iot:testmodel;1",
9+
"@type": "Interface",
10+
"contents": [
11+
{
12+
"@type": [
13+
"Telemetry",
14+
"Historized"
15+
],
16+
"displayName": "Status Data timestamp",
17+
"name": "StatusTimestamp",
18+
"schema": "dateTime"
19+
},
20+
{
21+
"@type": [
22+
"Telemetry",
23+
"Historized"
24+
],
25+
"displayName": "Operating Mode",
26+
"name": "OperatingMode",
27+
"schema": "string"
28+
},
29+
{
30+
"@type": [
31+
"Telemetry",
32+
"Historized",
33+
"Validated"
34+
],
35+
"displayName": "Current Battery Charge Percentage",
36+
"name": "CurrentChargePercentage",
37+
"schema": "integer",
38+
"minimum": 0,
39+
"maximum": 100
40+
},
41+
{
42+
"@type": [
43+
"Telemetry",
44+
"Historized",
45+
"Validated"
46+
],
47+
"displayName": "Reserved Battery Charge Percentage",
48+
"name": "ReservedChargePercentage",
49+
"schema": "integer",
50+
"minimum": 0,
51+
"maximum": 100
52+
},
53+
{
54+
"@type": [
55+
"Telemetry",
56+
"Historized"
57+
],
58+
"displayName": "Update comment",
59+
"name": "comment",
60+
"schema": "string"
61+
}
62+
]
63+
}

IotDemoGateway/OCISetup/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
/OCIDs.sh
2+
/OCIPoliciesReal.txt
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
# run this in the DigitalTwin directory
2+
# these should not be shared outside oracle
3+
source ../OCISetup/OCIDs.sh
4+
5+
# change these names as required
6+
export IOT_DOMAIN_GROUP_NAME=iot-domain-group-timg
7+
export IOT_DOMAIN_NAME=iot-domain-timg
8+
9+
10+
export DIGITAL_TWIN_MODEL_NAME=testmodel
11+
export DIGITAL_TWIN_MODEL_FILE_NAME=testmodel.json
12+
export DIGITAL_TWIN_MODEL_FILE=file://$DIGITAL_TWIN_MODEL_FILE_NAME
13+
14+
export DIGITAL_TWIN_ADAPTOR_ROUTE_MAPPINGS_FILE=file://testadapter.json
15+
export DIGITAL_TWIN_ADAPTOR_ENVELOPE_MAPPINGS_FILE=file://testenvelope.json
16+
export DIGITAL_TWIN_ADAPTER_NAME=testadapter
17+
18+
if [[ -z "$IOT_COMPARTMENT_OCID" ]]
19+
then
20+
echo "IOT_COMPARTMENT_OCID is not set, this should contain the compartment ocid that contains the IOT domain group and other resources"
21+
fi
22+
23+
export IOT_DOMAIN_GROUP_OCID=`oci iot domain-group list --display-name $IOT_DOMAIN_GROUP_NAME --compartment-id $IOT_COMPARTMENT_OCID | jq -r '.data.items[]| select (."lifecycle-state" == "ACTIVE") | ."id"'`
24+
if [[ -z "$IOT_DOMAIN_GROUP_OCID" ]]
25+
then
26+
echo Creating IotDomainGroup $IOT_DOMAIN_GROUP_NAME
27+
# Create the IoT Domain Group imstructions at https://docs.oracle.com/en-us/iaas/Content/internet-of-things/create-domain-group.htm
28+
# to make sure it's in a ready state
29+
echo oci iot domain-group create --compartment-id $IOT_COMPARTMENT_OCID --display-name $IOT_DOMAIN_GROUP_NAME --wait-for-state SUCCEEDED --wait-for-state FAILED
30+
oci iot domain-group create --compartment-id $IOT_COMPARTMENT_OCID --display-name $IOT_DOMAIN_GROUP_NAME --wait-for-state SUCCEEDED --wait-for-state FAILED
31+
# get the domain group ocid (only run this once' it's created)
32+
export IOT_DOMAIN_GROUP_OCID=`oci iot domain-group list --display-name $IOT_DOMAIN_GROUP_NAME --compartment-id $IOT_COMPARTMENT_OCID | jq -r '.data.items[]| select (."lifecycle-state" == "ACTIVE") | ."id"'`
33+
# get the data host
34+
export IOT_DOMAIN_GROUP_DATA_HOST=`oci iot domain-group get --iot-domain-group-id $IOT_DOMAIN_GROUP_OCID | jq -r '.data."data-host"'`
35+
export IOT_DOMAIN_GROUP_SHORT_ID=`echo $IOT_DOMAIN_GROUP_DATA_HOST| tr '.' ' ' | awk '{print $1}'`
36+
echo Created IotDomainGroup $IOT_DOMAIN_GROUP_NAME
37+
else
38+
echo "Iot Domain Group $IOT_DOMAIN_GROUP_NAME already exists"
39+
fi
40+
41+
export IOT_DOMAIN_OCID=`oci iot domain list --display-name $IOT_DOMAIN_NAME --compartment-id $IOT_COMPARTMENT_OCID --iot-domain-group-id $IOT_DOMAIN_GROUP_OCID | jq -r '.data.items[]| select (."lifecycle-state" == "ACTIVE") | ."id"'`
42+
if [[ -z "$IOT_DOMAIN_OCID" ]]
43+
then
44+
echo Creating IotDomain $IOT_DOMAIN_NAME
45+
#Create the IoT domain within the group
46+
echo oci iot domain create --compartment-id $IOT_COMPARTMENT_OCID --display-name $IOT_DOMAIN_NAME --iot-domain-group-id $IOT_DOMAIN_GROUP_OCID --wait-for-state SUCCEEDED --wait-for-state FAILED
47+
oci iot domain create --compartment-id $IOT_COMPARTMENT_OCID --display-name $IOT_DOMAIN_NAME --iot-domain-group-id $IOT_DOMAIN_GROUP_OCID --wait-for-state SUCCEEDED --wait-for-state FAILED
48+
# this will return on success or fail, also this may start a work request, which runs in the background, use this command to see if it's created
49+
oci iot domain list --display-name $IOT_DOMAIN_NAME --compartment-id $IOT_COMPARTMENT_OCID --iot-domain-group-id $IOT_DOMAIN_GROUP_OCID
50+
#Get the OCID we will need
51+
export IOT_DOMAIN_OCID=`oci iot domain list --display-name $IOT_DOMAIN_NAME --compartment-id $IOT_COMPARTMENT_OCID --iot-domain-group-id $IOT_DOMAIN_GROUP_OCID | jq -r '.data.items[]| select (."lifecycle-state" == "ACTIVE") | ."id"'`
52+
export IOT_DOMAIN_HOST=`oci iot domain get --iot-domain-id $IOT_DOMAIN_OCID | jq -r '.data."device-host"'`
53+
export IOT_DOMAIN_SHORT_ID=`echo $IOT_DOMAIN_HOST| tr '.' ' ' | awk '{print $1}'`
54+
echo Created IotDomain $IOT_DOMAIN_NAME
55+
else
56+
echo "Iot Domain $IOT_DOMAIN_NAME already exists"
57+
fi
58+
59+
60+
export DIGITAL_TWIN_MODEL_ID=`oci iot digital-twin-model list --iot-domain-id $IOT_DOMAIN_OCID --display-name $DIGITAL_TWIN_MODEL_NAME | jq -r '.data.items[]| select (."lifecycle-state" == "ACTIVE") | ."id"'`
61+
if [[ -z "$DIGITAL_TWIN_MODEL_ID" ]]
62+
then
63+
echo Creating Digital Twin Model $DIGITAL_TWIN_MODEL_NAME
64+
# Create the digtal twin model for the generic home battery, run from within the DigitalTwin folder
65+
echo oci iot digital-twin-model create --iot-domain-id $IOT_DOMAIN_OCID --display-name $DIGITAL_TWIN_MODEL_NAME --spec $DIGITAL_TWIN_MODEL_FILE --wait-for-state ACTIVE
66+
oci iot digital-twin-model create --iot-domain-id $IOT_DOMAIN_OCID --display-name $DIGITAL_TWIN_MODEL_NAME --spec $DIGITAL_TWIN_MODEL_FILE --wait-for-state ACTIVE
67+
# get the id of the model you just created
68+
export DIGITAL_TWIN_MODEL_ID=`oci iot digital-twin-model list --iot-domain-id $IOT_DOMAIN_OCID --display-name $DIGITAL_TWIN_MODEL_NAME | jq -r '.data.items[]| select (."lifecycle-state" == "ACTIVE") | ."id"'`
69+
echo Created Digital Twin Model $DIGITAL_TWIN_MODEL_NAME
70+
else
71+
echo "Digital twin model $DIGITAL_TWIN_MODEL_NAME already exists"
72+
fi
73+
# and the models name
74+
export DIGITAL_TWIN_MODEL_IDENTIFIER=`cat $DIGITAL_TWIN_MODEL_FILE_NAME | jq -r '.["@id"]'`
75+
76+
77+
export DIGITAL_TWIN_ADAPTER_OCID=`oci iot digital-twin-adapter list --iot-domain-id $IOT_DOMAIN_OCID --display-name $DIGITAL_TWIN_ADAPTER_NAME | jq -r '.data.items[]| select (."lifecycle-state" == "ACTIVE") | ."id"'`
78+
if [[ -z "$DIGITAL_TWIN_ADAPTER_OCID" ]]
79+
then
80+
echo Creating Digital Twin adapter $DIGITAL_TWIN_ADAPTER_NAME
81+
# create the adaptor using the multiple routes file.
82+
# note that as the file contents is inlined into the JSON request then the stricture of the JSON files MUST be OK (if not you'll get missing param errors, even though you have specifried all fo the actual flags correctly
83+
echo oci iot digital-twin-adapter create --iot-domain-id $IOT_DOMAIN_OCID --digital-twin-model-id $DIGITAL_TWIN_MODEL_ID --inbound-routes $DIGITAL_TWIN_ADAPTOR_ROUTE_MAPPINGS_FILE --display-name $DIGITAL_TWIN_ADAPTER_NAME --inbound-envelope $DIGITAL_TWIN_ADAPTOR_ENVELOPE_MAPPINGS_FILE --wait-for-state ACTIVE
84+
oci iot digital-twin-adapter create --iot-domain-id $IOT_DOMAIN_OCID --digital-twin-model-id $DIGITAL_TWIN_MODEL_ID --inbound-routes $DIGITAL_TWIN_ADAPTOR_ROUTE_MAPPINGS_FILE --display-name $DIGITAL_TWIN_ADAPTER_NAME --inbound-envelope $DIGITAL_TWIN_ADAPTOR_ENVELOPE_MAPPINGS_FILE --wait-for-state ACTIVE
85+
# get the OCID of the new adaptor
86+
export DIGITAL_TWIN_ADAPTER_OCID=`oci iot digital-twin-adapter list --iot-domain-id $IOT_DOMAIN_OCID --display-name $DIGITAL_TWIN_ADAPTER_NAME | jq -r '.data.items[]| select (."lifecycle-state" == "ACTIVE") | ."id"'`
87+
echo Created Digital Twin adapter $DIGITAL_TWIN_ADAPTER_NAME
88+
else
89+
echo "Digital twin adapter $DIGITAL_TWIN_ADAPTER_NAME already exists"
90+
fi
91+
echo Remember, no digital twin instances have been created
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
2+
# change these names as required
3+
source ../OCISetup/OCIDs.sh
4+
export IOT_DOMAIN_GROUP_NAME=iot-domain-group-timg
5+
export IOT_DOMAIN_NAME=iot-domain-timg
6+
export GENERATED_SECRET_PREFIX_NAME='iot-gateway-generated-secret*'
7+
8+
if [[ -z "$IOT_COMPARTMENT_OCID" ]]
9+
then
10+
echo "IOT_COMPARTMENT_OCID is not set, this should contain the compartment ocid that contains the IOT domain group and other resources"
11+
fi
12+
13+
echo Getting OCIDs
14+
export IOT_DOMAIN_GROUP_OCID=`oci iot domain-group list --display-name $IOT_DOMAIN_GROUP_NAME --compartment-id $IOT_COMPARTMENT_OCID | jq -r '.data.items[]| select (."lifecycle-state" == "ACTIVE") | ."id"'`
15+
if [[ -n "$IOT_DOMAIN_GROUP_OCID" ]]
16+
then
17+
echo "Got iotdomaingroup ocid, looking for domain"
18+
export IOT_DOMAIN_OCID=`oci iot domain list --display-name $IOT_DOMAIN_NAME --compartment-id $IOT_COMPARTMENT_OCID --iot-domain-group-id $IOT_DOMAIN_GROUP_OCID | jq -r '.data.items[]| select (."lifecycle-state" == "ACTIVE") | ."id"'`
19+
else
20+
echo "Can't locate IOT domain group so can't locate iot domain"
21+
fi
22+
23+
if [[ -n "$IOT_DOMAIN_OCID" ]]
24+
then
25+
echo "Deleting IotDomain $IOT_DOMAIN_NAME"
26+
oci iot domain delete --iot-domain-id $IOT_DOMAIN_OCID --force --wait-for-state SUCCEEDED --wait-for-state FAILED
27+
echo "Deleted IotDomain $IOT_DOMAIN_NAME"
28+
else
29+
echo "No iot domain to delete"
30+
fi
31+
32+
if [[ -n "$IOT_DOMAIN_GROUP_OCID" ]]
33+
then
34+
echo "Deleting IotDomainGroup $IOT_DOMAIN_GROUP_NAME"
35+
oci iot domain-group delete --iot-domain-group-id $IOT_DOMAIN_GROUP_OCID --force --wait-for-state SUCCEEDED --wait-for-state FAILED
36+
echo "Deleted IotDomainGroup $IOT_DOMAIN_GROUP_NAME"
37+
else
38+
echo "No iot domain group to delete"
39+
fi
40+
41+
42+
43+
# get the list of secrets in the vault
44+
echo "Looking for any generated secrets to delete"
45+
for secretname in `oci vault secret list --compartment-id $IOT_COMPARTMENT_OCID --all --lifecycle-state ACTIVE | jq -r '.data[] | ."secret-name"'` ; do
46+
if [[ $secretname = $GENERATED_SECRET_PREFIX_NAME ]]
47+
then
48+
echo "$secretname is a generated secret, getting ocid"
49+
SECRET_OCID=`oci vault secret list --compartment-id $IOT_COMPARTMENT_OCID --name $secretname --lifecycle-state ACTIVE --all | jq -r '.data[0].id'`
50+
SECRET_DELETE_TIME=`date -j -v+1d -v+5M +"%Y-%m-%dT%H:%M:%S%z"`
51+
echo "Scheduling deletion of $secretname with ocid $SECRET_OCID for $SECRET_DELETE_TIME"
52+
oci vault secret schedule-secret-deletion --secret-id $SECRET_OCID --time-of-deletion $SECRET_DELETE_TIME
53+
else
54+
echo "no match, ignoring $secretname"
55+
fi
56+
done
57+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
IoT policy - apply in the tim.graves compartment, you will need to get the vault OCID and substitute it
2+
Allow group OracleIdentityCloudService/Domain_Specialists to manage iot-family in compartment tim.graves
3+
Allow any-user to {SECRET_BUNDLE_READ, SECRET_READ} in compartment tim.graves where ALL {request.principal.type = 'iotdomain', target.vault.id = '<VAULT OCID>'}
4+
Allow any-user to {CERTIFICATE_BUNDLE_READ, CERTIFICATE_READ} in compartment tim.graves where request.principal.type = 'iotdomain'
5+
Allow any-user to {CERTIFICATE_AUTHORITY_BUNDLE_READ, CERTIFICATE_AUTHORITY_READ} in compartment tim.graves where request.principal.type = 'iotdomain'
6+
Allow any-user to {CABUNDLE_READ} in compartment tim.graves where request.principal.type = 'iotdomain'
7+
Allow any-user to {VCN_READ} in compartment tim.graves where request.principal.type = 'iotdomain'

0 commit comments

Comments
 (0)