Commit dc19715e authored by dwentzel's avatar dwentzel
Browse files

setup

parent afefbb5e
[also see this for other queries](working_asa_code.txt) and the working queries on demo-README.md at the bottom
code:
```sql
WITH Telemetry AS
(
-- Web Simulator Devices
SELECT
Stream.IoTHub.ConnectionDeviceId as DeviceID,
Ref.msdyn_name as DeviceName,
Ref.msdyn_iotdeviceid as iotdeviceid,
System.TimeStamp AS EventTime, --This is based on TIMESTAMP BY IoTHub.EnqueuedTime which is the time the message was placed in IoTHub
Ref._msdyn_account_value as accountid,
AVG(Ref.cfs_latitude) as Latitude,
AVG(Ref.cfs_longitude) as Longitude,
AVG(Stream.Temperature) as Fahreheit,
AVG(Stream.Humidity) as Humidity,
null as Pressure,
null as AccelerometerX,
null as AccelerometerY,
null as AccelerometerZ
FROM
IoTStream Stream TIMESTAMP BY IoTHub.EnqueuedTime
JOIN IotDeviceReference Ref
ON Stream.IoTHub.ConnectionDeviceId = Ref.msdyn_deviceid
WHERE
Stream.EventToken IS NOT NULL
GROUP BY Ref._msdyn_account_value, Stream.IoTHub.ConnectionDeviceId, Ref.msdyn_name, Ref.msdyn_iotdeviceid, TumblingWindow(second, 15)
UNION
--MX Chip Telemetry Data
SELECT
Stream.IoTHub.ConnectionDeviceId as DeviceID,
Ref.msdyn_name as DeviceName,
Ref.msdyn_iotdeviceid as iotdeviceid,
System.TimeStamp AS EventTime, --This is based on TIMESTAMP BY IoTHub.EnqueuedTime which is the time the message was placed in IoTHub
Ref._msdyn_account_value as accountid,
AVG(Ref.cfs_latitude) as Latitude,
AVG(Ref.cfs_longitude) as Longitude,
AVG(((Stream.temp*1.8)+(32-7))) as Fahreheit,
AVG(Stream.humidity) as Humidity,
AVG(Stream.pressure) as Pressure,
MIN(Stream.accelerometerX) as AccelerometerX,
MIN(Stream.accelerometerY) as AccelerometerY,
MIN(Stream.accelerometerZ) as AccelerometerZ
FROM
IoTStream Stream TIMESTAMP BY IoTHub.EnqueuedTime
JOIN IotDeviceReference Ref
ON Stream.IoTHub.ConnectionDeviceId = Ref.msdyn_deviceid
WHERE
Stream.temp IS NOT NULL
GROUP BY Ref._msdyn_account_value, Stream.IoTHub.ConnectionDeviceId, Ref.msdyn_name, Ref.msdyn_iotdeviceid, TumblingWindow(second, 15)
),
/*
*** EXPLANATION OF THE ANOMALYDETECTION_DIP FUNCTION ***
ANOMALYDETECTION_DIP(<scalar_expression>, <tukey_sensitivity>, <zscore_sensitivity>, [<minimum_training_event_count>],)
OVER ([PARTITION BY <partition key>] LIMIT DURATION(<unit>, <length>) [WHEN boolean_expression])
Z = (event value – mean) / (standard deviation)
*/
AnomalyDetectionStep AS (
SELECT
*,
system.timestamp as anomalyDetectionStepTimestamp,
AnomalyDetection_SpikeAndDip(Fahreheit, 99, 40, 'spikesanddips') OVER(LIMIT DURATION(mi, 10)) as SpikeAndDipScores
FROM Telemetry
)
/*
-- Send summarized data to testoutput
SELECT
DeviceID,
DeviceName,
EventTime,
iotdeviceid,
accountid,
Latitude,
Longitude,
Fahreheit,
Humidity,
Pressure,
AccelerometerX,
AccelerometerY,
AccelerometerZ,
CAST(GetRecordPropertyValue(scores, 'ZScore') as float) as ZScore,
CAST(GetRecordPropertyValue(scores, 'ZScoreAnomaly') as bigint) as ZScoreAnomaly
INTO testoutput
FROM AnomalyDetectionStep
*/
-- Send summarized data to CosmosDB
SELECT
DeviceID,
DeviceName,
EventTime,
--DATEADD(hour, -4, EventTime) AS EventTime, --EDT US
--DATEADD(hour, -5, EventTime) AS EventTime, --EST US
iotdeviceid,
accountid,
Latitude,
Longitude,
Fahreheit,
Humidity,
Pressure,
AccelerometerX,
AccelerometerY,
AccelerometerZ,
CAST(GetRecordPropertyValue(SpikeAndDipScores, 'Score') as float) as SpikeAndDipScore,
CAST(GetRecordPropertyValue(SpikeAndDipScores, 'IsAnomaly') as bigint) as IsSpikeAndDipAnomaly
INTO CosmosDB
FROM AnomalyDetectionStep
-- Send summarized data to Power BI
SELECT
DeviceID,
DeviceName as 'Device Name',
EventTime AS "EventTime UTC",
DATEADD(hour, -4, EventTime) AS EventTime, --EDT US
--DATEADD(hour, -5, EventTime) AS EventTime, --EST US
Latitude,
Longitude,
Fahreheit,
Humidity,
Pressure,
accelerometerX as 'Accelerometer X',
accelerometerY as 'Accelerometer Y',
accelerometerZ as 'Accelerometer Z',
CAST(GetRecordPropertyValue(SpikeAndDipScores, 'Score') as float) as SpikeAndDipScore,
CAST(GetRecordPropertyValue(SpikeAndDipScores, 'IsAnomaly') as bigint) as IsSpikeAndDipAnomaly
INTO PowerBI
FROM AnomalyDetectionStep
-- Send Alerts to Service Bus Message Queue for Dynamics 365
SELECT
'null' as ID,
DeviceID,
'Temperature' AS ReadingType,
Fahreheit as reading,
EventTime as time,
--DATEADD(hour, -4, EventTime) as time, --EDT US
CAST(GetRecordPropertyValue(SpikeAndDipScores, 'IsAnomaly') as bigint) as abn
INTO AlertsQueue
FROM AnomalyDetectionStep
WHERE CAST(GetRecordPropertyValue(SpikeAndDipScores, 'IsAnomaly') as float) = 1
```
\ No newline at end of file
* http://git.davewentzel.com/demos/iot.git (private)
* https://git.davewentzel.com/demos/iot.git (private)
* https://github.com/davew-msft/mxchip.git (private)
## My IoT Analytics Demo using the MXChip
......@@ -19,6 +19,8 @@ Objectives are:
* also follow the instructions to setup the dev env with vscode including the arduino gui
* you do not need to do the "Build your first project" instructions
**I don't think the firmware in the instruction above works, but I can't find my exact instructions.** [I have some documentation here](firmware.md).
* Button B cycles through the sensors.
* [manually setup wifi with putty](https://microsoft.github.io/azure-iot-developer-kit/docs/use-configuration-mode/)
* in azure: rgiotdevkit (airs)
......
......@@ -25,8 +25,19 @@ Need DeviceRulesBlob
* based on the ASA output to the anomaly SB q (similar to twilio), sends a message to IoTHub to activate the rainbow lights
* [LogicApp-ConnectionState](conn-state.md)
* when a request is made this looks up the state of the device in `dbo.ConnectionState`
SignalBacktoMXChip
Temp-Send-Text
* [LogicApp-SignalBacktoMXChip](signal-back.md)
* shows the general pattern to send messages to an IoT device
* send the message to a q (ourcs is called `signaltodevice`)
* this logic app polls that q, gets the messages, and sends them to IoTHub
* [LogicApp-SendTempText](temp.md)
* read a q (sms)
* parse json
* very similar to Shake and Text
* [ASA-AnomalyDetectionAlertQ](ASA-alert.md)
* read from IoTStream
* see query
* output to a Q, Cosmos, PBI, debugger if needed
### Other ASA queries:
......
[mxchip info](https://www.mxchip.com/az3166)
I think this is what I followed [from here](https://github.com/jcbendernh/MX-Chip-with-Dynamics-365-Connected-Field-Service)
Download the Dec 4, 2017 release of the firmware which is the AZ3166-IoT-Central-1.0.0.bin file from GitHub at https://github.com/Microsoft/microsoft-iot-central-firmware/releases.
NOTE: Do not download the latest release as it has an issue with receiving the Method Name commands.
Follow the instructions in the Prepare the DevKit device section at https://docs.microsoft.com/en-us/microsoft-iot-central/howto-connect-devkit. When you get to step 7 and you configure the device in the web page at http://192.168.0.1/start make sure to copy your Connection string – primary key from Notepad into the Device connection string field and select the Temperature checkbox at a minimum. You can select the other telemetry as well, but it is not needed for this specific scenario.
Click the Configure Device button and click the reset button on the MX Chip.
NOTE: If you do not get the Device connection string field in the window above, try doing a hard reset on the MX CHIP by holding down both the A & B buttons for a few seconds.
Now you should see telemetry coming from your custom named MX chip. You can view this by downloading the Azure Device Explorer Twin and pasting the IoT Hub Connection Sting into the Configuration tab. Once you have done so, go to the Data tab and select your device and click Monitor…
NOTE: The IoT Hub Connection string can be obtained by going into the Azure portal and under your Connected Field Service resource group, select your IoT Hub and click on the Shared access polices blade. Once it is loaded, click the iothubowner policy and copy the Connection string-primary key.
Since the MX Chip firmware for IoT Central device sends telemetry a little different than the web simulator or other devices, we will need to modify our queries for the Stream Analytics jobs. (I don't think I did this)
\ No newline at end of file
![](./img/signal1.png)
![](./img/signal2.png)
![](./img/signal3.png)
![](./img/signal4.png)
Code:
```json
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"For_each": {
"actions": {
"SendMessageToAnIotHubDevice": {
"inputs": {
"body": {
"ConnectionString": "HostName=cfs365.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=iNA1aioN5JsiTL/tefir5fqEtRs46ivA0Y8b0zJWa2Y=",
"DeviceId": "@items('For_each')['deviceid']",
"Message": "{\"methodName\": \"rainbow\",\"payload\": {\"cycles\": \"8\"}}"
},
"method": "post",
"uri": "https://iothubcfs3654818b81dadd642dfb4b9e36c6ff4b676.azurewebsites.net:443/SendMessage"
},
"metadata": {
"apiDefinitionUrl": "https://IoTHubcfs365rmc6d59f50732648afadece577666cc1cc.azurewebsites.net/swagger/docs/v1",
"swaggerSource": "website"
},
"runAfter": {},
"type": "Http"
}
},
"foreach": "@body('Parse_JSON')",
"runAfter": {
"Parse_JSON": [
"Succeeded"
]
},
"type": "Foreach"
},
"GetIotMessage": {
"inputs": {
"body": {
"ContentData": "@{triggerBody()['ContentData']}",
"ContentEncoding": "@{triggerBody()['ContentTransferEncoding']}",
"ContentType": "@{triggerBody()?['ContentType']}"
},
"method": "post",
"uri": "https://QueueMessageParsercfs3654900728808d749aba0a029eca.azurewebsites.net:443/ParseAMQPMessage"
},
"metadata": {
"apiDefinitionUrl": "https://QueueMessageParser.azurewebsites.net/swagger/docs/v1",
"swaggerSource": "website"
},
"runAfter": {},
"type": "Http"
},
"Parse_JSON": {
"inputs": {
"content": "@body('GetIotMessage')",
"schema": {
"items": {
"properties": {
"abn": {
"type": "number"
},
"deviceid": {
"type": "string"
},
"reading": {
"type": "number"
},
"readingtype": {
"type": "string"
},
"time": {
"type": "string"
}
},
"required": [
"deviceid",
"readingtype",
"reading",
"time",
"abn"
],
"type": "object"
},
"type": "array"
}
},
"runAfter": {
"GetIotMessage": [
"Succeeded"
]
},
"type": "ParseJson"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {
"$connections": {
"defaultValue": {},
"type": "Object"
}
},
"triggers": {
"When_a_message_is_received_in_a_queue_(auto-complete)": {
"inputs": {
"host": {
"connection": {
"name": "@parameters('$connections')['servicebus_1']['connectionId']"
}
},
"method": "get",
"path": "/@{encodeURIComponent(encodeURIComponent('signaltodevice'))}/messages/head",
"queries": {
"queueType": "Main"
}
},
"recurrence": {
"frequency": "Second",
"interval": 30
},
"type": "ApiConnection"
}
}
},
"parameters": {
"$connections": {
"value": {
"servicebus_1": {
"connectionId": "/subscriptions/c74df6e4-9f8a-488c-90d2-2ded5686ef83/resourceGroups/cfs365/providers/Microsoft.Web/connections/SBMessage",
"connectionName": "SBMessage",
"id": "/subscriptions/c74df6e4-9f8a-488c-90d2-2ded5686ef83/providers/Microsoft.Web/locations/eastus/managedApis/servicebus"
}
}
}
}
}
```
\ No newline at end of file
![](./img/temp.png)
Code
```json
{
"definition": {
"$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
"actions": {
"ParseJSON": {
"inputs": {
"content": "@json(substring(decodeBase64(triggerBody()?['ContentData']),63,sub(length(decodeBase64(triggerBody()?['ContentData'])),63)))",
"schema": {
"properties": {
"abn": {
"type": "number"
},
"deviceid": {
"type": "string"
},
"reading": {
"type": "number"
},
"readingtype": {
"type": "string"
},
"time": {
"type": "string"
}
},
"type": "object"
}
},
"runAfter": {},
"type": "ParseJson"
},
"Send_Text_Message_(SMS)": {
"inputs": {
"body": {
"body": "The @{body('ParseJSON')?['readingtype']} reading of @{body('ParseJSON')?['reading']} was anomalous for the following device:@{body('ParseJSON')?['deviceid']} . Event Timestamp: @{body('ParseJSON')?['time']}",
"from": "+19782212719",
"to": "+1 (603) 566-7570"
},
"host": {
"connection": {
"name": "@parameters('$connections')['twilio']['connectionId']"
}
},
"method": "post",
"path": "/Messages.json"
},
"runAfter": {
"ParseJSON": [
"Succeeded"
]
},
"type": "ApiConnection"
}
},
"contentVersion": "1.0.0.0",
"outputs": {},
"parameters": {
"$connections": {
"defaultValue": {},
"type": "Object"
}
},
"triggers": {
"ServiceBusQueueItem": {
"inputs": {
"host": {
"connection": {
"name": "@parameters('$connections')['servicebus_1']['connectionId']"
}
},
"method": "get",
"path": "/@{encodeURIComponent(encodeURIComponent('sms'))}/messages/head",
"queries": {
"queueType": "Main"
}
},
"recurrence": {
"frequency": "Second",
"interval": 30
},
"type": "ApiConnection"
}
}
},
"parameters": {
"$connections": {
"value": {
"servicebus_1": {
"connectionId": "/subscriptions/c74df6e4-9f8a-488c-90d2-2ded5686ef83/resourceGroups/cfs365/providers/Microsoft.Web/connections/servicebus",
"connectionName": "servicebus",
"id": "/subscriptions/c74df6e4-9f8a-488c-90d2-2ded5686ef83/providers/Microsoft.Web/locations/eastus/managedApis/servicebus"
},
"twilio": {
"connectionId": "/subscriptions/c74df6e4-9f8a-488c-90d2-2ded5686ef83/resourceGroups/cfs365/providers/Microsoft.Web/connections/twilio",
"connectionName": "twilio",
"id": "/subscriptions/c74df6e4-9f8a-488c-90d2-2ded5686ef83/providers/Microsoft.Web/locations/eastus/managedApis/twilio"
}
}
}
}
}
```
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment