Ga develop (#47)
* [update] BREAKING CHANGE: support IoT Edge GA [update] remove #IOT_EDGE debugging flag, since IoT Edge now can debug into containers [fix] fix GetConnectionType() exception * [update] update README * [fix] fix Dockerfile for arm32v7
This commit is contained in:
Родитель
e9b77ac27e
Коммит
9a98463481
|
@ -1,20 +0,0 @@
|
|||
FROM arm32v7/gcc:7 AS build-env
|
||||
WORKDIR /app
|
||||
|
||||
# copy .c and .h file
|
||||
COPY src/*.c ./
|
||||
COPY src/*.h ./
|
||||
|
||||
# build
|
||||
RUN gcc -shared -o libcomWrapper.so -fPIC comWrapper.c
|
||||
|
||||
FROM microsoft/dotnet:2.0.0-runtime-stretch-arm32v7
|
||||
|
||||
ARG EXE_DIR=.
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY $EXE_DIR/ ./
|
||||
COPY --from=build-env /app/libcomWrapper.so /usr/lib/
|
||||
|
||||
CMD ["/usr/bin/dotnet", "iot-edge-modbus.dll"]
|
|
@ -1,20 +0,0 @@
|
|||
FROM gcc:7 AS build-env
|
||||
WORKDIR /app
|
||||
|
||||
# copy .c and .h file
|
||||
COPY src/*.c ./
|
||||
COPY src/*.h ./
|
||||
|
||||
# build
|
||||
RUN gcc -shared -o libcomWrapper.so -fPIC comWrapper.c
|
||||
|
||||
FROM microsoft/dotnet:2.0.0-runtime-stretch-arm32v7
|
||||
|
||||
ARG EXE_DIR=.
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY $EXE_DIR/ ./
|
||||
COPY --from=build-env /app/libcomWrapper.so /usr/lib
|
||||
|
||||
CMD ["/usr/bin/dotnet", "iot-edge-modbus.dll"]
|
|
@ -1,20 +0,0 @@
|
|||
FROM gcc:7 AS build-env
|
||||
WORKDIR /app
|
||||
|
||||
# copy .c and .h file
|
||||
COPY src/*.c ./
|
||||
COPY src/*.h ./
|
||||
|
||||
# build
|
||||
RUN gcc -shared -o libcomWrapper.so -fPIC comWrapper.c
|
||||
|
||||
FROM microsoft/dotnet:2.0.0-runtime
|
||||
|
||||
ARG EXE_DIR=.
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY $EXE_DIR/ ./
|
||||
COPY --from=build-env /app/libcomWrapper.so /usr/lib/
|
||||
|
||||
CMD ["/usr/bin/dotnet", "iot-edge-modbus.dll"]
|
|
@ -1,9 +0,0 @@
|
|||
FROM microsoft/dotnet:2.0.0-runtime-nanoserver-1709
|
||||
|
||||
ARG EXE_DIR=.
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY $EXE_DIR/ ./
|
||||
|
||||
CMD ["dotnet", "iot-edge-modbus.dll"]
|
|
@ -1,20 +0,0 @@
|
|||
FROM microsoft/dotnet:2.0-sdk-nanoserver-1709 AS build-env
|
||||
WORKDIR /app
|
||||
|
||||
# copy csproj and restore as distinct layers
|
||||
COPY src/*.cs* ./
|
||||
RUN dotnet restore
|
||||
|
||||
# build
|
||||
RUN dotnet build
|
||||
RUN dotnet publish -f netcoreapp2.0 -c Release -o out
|
||||
|
||||
FROM microsoft/dotnet:2.0.0-runtime-nanoserver-1709
|
||||
|
||||
ARG EXE_DIR=.
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=build-env /app/out ./
|
||||
|
||||
CMD ["dotnet", "iot-edge-modbus.dll"]
|
201
README.md
201
README.md
|
@ -1,16 +1,16 @@
|
|||
This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments
|
||||
|
||||
# Azure IoT Edge Modbus Module Preview #
|
||||
# Azure IoT Edge Modbus Module GA #
|
||||
Using this module, developers can build Azure IoT Edge solutions with Modbus TCP/RTU(RTU is currently not available in Windows container) connectivity. The Modbus module is an [Azure IoT Edge](https://github.com/Azure/iot-edge) module, capable of reading data from Modbus devices and publishing data to the Azure IoT Hub via the Edge framework. Developers can modify the module tailoring to any scenario. Alternatively, the module can also be run in standalone mode for debug purpose, which doesn't require IoT Edge framework.
|
||||
|
||||
![](./doc/diagram.png)
|
||||
|
||||
There are prebuilt Modbus TCP module container images ready at [microsoft/azureiotedge-modbus-tcp:1.0-preview](https://hub.docker.com/r/microsoft/azureiotedge-modbus-tcp) for you to quickstart the experience of Azure IoT Edge on your target device or simulated device.
|
||||
There are prebuilt Modbus TCP module container images ready at [TBD-link](https://hub.docker.com/r/microsoft/azureiotedge-modbus-tcp) for you to quickstart the experience of Azure IoT Edge on your target device or simulated device.
|
||||
|
||||
Visit http://azure.com/iotdev to learn more about developing applications for Azure IoT.
|
||||
|
||||
## Azure IoT Edge Compatibility ##
|
||||
Current version of the module is targeted for the [Azure IoT Edge (second version in public preview)](https://github.com/Azure/azure-iot-edge).
|
||||
Current version of the module is targeted for the [Azure IoT Edge GA](https://azure.microsoft.com/en-us/blog/azure-iot-edge-generally-available-for-enterprise-grade-scaled-deployments/).
|
||||
If you are using [v1 version of IoT Edge](https://github.com/Azure/iot-edge/tree/master/v1) (previously known as Azure IoT Gateway), please use v1 version of this module, all materials can be found in [v1](https://github.com/Azure/iot-edge-modbus/tree/master/v1) folder.
|
||||
|
||||
Find more information about Azure IoT Edge at [here](https://docs.microsoft.com/en-us/azure/iot-edge/how-iot-edge-works).
|
||||
|
@ -32,47 +32,24 @@ Azure IoT Edge is designed to be used with a broad range of operating system pla
|
|||
|
||||
|
||||
## Build Environment Setup ##
|
||||
Modbus module is a .NET Core 2.0 application, which is developed and built based on the guidelines in Azure IoT Edge document.
|
||||
Modbus module is a .NET Core 2.1 application, which is developed and built based on the guidelines in Azure IoT Edge document.
|
||||
Please follow [this link](https://docs.microsoft.com/en-us/azure/iot-edge/tutorial-csharp-module) to setup the build environment.
|
||||
|
||||
Basic requirement:
|
||||
- Docker CE
|
||||
- .NET Core 2.0 SDK (optional, if you prefer to manually build application on host machine)
|
||||
- .NET Core 2.1 SDK
|
||||
|
||||
## HowTo Build ##
|
||||
In this section, the Modbus TCP module we be built as an IoT Edge module.
|
||||
In this section, the Modbus module we be built as an IoT Edge module.
|
||||
|
||||
Dockerfiles are located under [Docker](https://github.com/Azure/iot-edge-modbus/tree/master/Docker) folder, you should be able to find one for your platform. There are two Dockerfiles in each platform, choose either one for your build preference.
|
||||
- "Dockerfile-auto": For multi-stage build, which will build application inside container and generate a target container image.
|
||||
- "Dockerfile": This requires you to build applicaiton on host machine and then use this Dockerfile to copy application binary to generate target container image.
|
||||
Open the project in VS Code, and open VS Code command palette, type and run the command Edge: Build IoT Edge solution.
|
||||
Select the deployment.template.json file for your solution from the command palette.
|
||||
***Note: Be sure to check [configuration section](https://github.com/Azure/iot-edge-modbus#configuration) to properly set each fields before deploying the module.***
|
||||
|
||||
**Note**: [Multi-stage](https://github.com/Azure/iot-edge-modbus#multi-stage-build) build for Linux-arm32 doesn't work at this moment, please do with [single-stage](https://github.com/Azure/iot-edge-modbus#single-stage-build) build.
|
||||
**Note**: Please replace \<platform\> in below scripts with the actual platform path you are trying to build.
|
||||
|
||||
### Build as an IoT Edge module ###
|
||||
1. Open "Program.cs" file in [src](https://github.com/Azure/iot-edge-modbus/tree/master/src) folder.
|
||||
2. Confirm **IOT_EDGE** flag is enabled at first line code.
|
||||
```csharp
|
||||
#define IOT_EDGE
|
||||
```
|
||||
|
||||
#### Multi-stage build ###
|
||||
Run docker build with the following commands.
|
||||
```sh
|
||||
$cd iot-edge-modbus/
|
||||
$docker build -t "modbus:latest" -f Docker/<PlatForm>/Dockerfile-auto .
|
||||
```
|
||||
|
||||
#### Single-stage build ####
|
||||
Run docker build with the following commands.
|
||||
```sh
|
||||
$cd iot-edge-modbus/src/
|
||||
$dotnet restore
|
||||
$dotnet build
|
||||
$dotnet publish -f netcoreapp2.0 -c Release
|
||||
$cd ../
|
||||
$docker build --build-arg EXE_DIR=./src/bin/Release/netcoreapp2.0/publish -t "modbus:latest" -f Docker/<PlatForm>/Dockerfile .
|
||||
```
|
||||
In Azure IoT Hub Devices explorer, right-click an IoT Edge device ID, then select Create deployment for IoT Edge device.
|
||||
Open the config folder of your solution, then select the deployment.json file. Click Select Edge Deployment Manifest.
|
||||
Then you can see the deployment is successfully created with a deployment ID in VS Code integrated terminal.
|
||||
You can check your container status in the VS Code Docker explorer or by run the docker ps command in the terminal.
|
||||
|
||||
## Configuration ##
|
||||
Before running the module, proper configuration is required. Here is a sample configuration for your reference.
|
||||
|
@ -137,7 +114,7 @@ Meaning of each field:
|
|||
* "PublishInterval" - Interval between each push to IoT Hub in millisecond
|
||||
* "SlaveConfigs" - Contains one or more Modbus slaves' configuration. In this sample, we have "Slave01" and "Slave02" two devices:
|
||||
* "Slave01", "Slave02" - User defined names for each Modbus slave, cannot have duplicates under "SlaveConfigs".
|
||||
* "SlaveConnection" - Ipv4 address or the serial port name of the Modbus slave
|
||||
* "SlaveConnection" - Ipv4 address or the serial port name of the Modbus slave.
|
||||
* "RetryCount" - Max retry attempt for reading data, default to 10
|
||||
* "RetryInterval" - Retry interval between each retry attempt, default to 50 milliseconds
|
||||
* "HwId" - Unique Id for each Modbus slave (user defined)
|
||||
|
@ -152,7 +129,7 @@ Meaning of each field:
|
|||
* "UnitId" - The unit id to be read
|
||||
* "StartAddress" - The starting address of Modbus read request, currently supports both 5-digit and 6-digit [format](https://en.wikipedia.org/wiki/Modbus#Coil.2C_discrete_input.2C_input_register.2C_holding_register_numbers_and_addresses)
|
||||
* "Count" - Number of registers/bits to be read
|
||||
* "DisplayName" - Alternative name for the "StartAddress" register(s)(user defined)
|
||||
* "DisplayName" - Alternative name for the "StartAddress" register(s)(user defined)
|
||||
* "CorrelationId" - The Operations with same id with be grouped together in their output message
|
||||
|
||||
For more about Modbus, please refer to the [Wiki](https://en.wikipedia.org/wiki/Modbus) link.
|
||||
|
@ -173,69 +150,69 @@ Message Properties:
|
|||
```
|
||||
Message Payload:
|
||||
```json
|
||||
[
|
||||
{
|
||||
"PublishTimestamp": "2018-04-17 12:28:53",
|
||||
"Content": [
|
||||
{
|
||||
"HwId": "PowerMeter-0a:01:01:01:01:02",
|
||||
"Data": [
|
||||
{
|
||||
"CorrelationId": "MessageType1",
|
||||
"SourceTimestamp": "2018-04-17 12:28:48",
|
||||
"Values": [
|
||||
{
|
||||
"DisplayName": "Op02",
|
||||
"Address": "40003",
|
||||
"Value": "2785"
|
||||
},
|
||||
{
|
||||
"DisplayName": "Op02",
|
||||
"Address": "40004",
|
||||
"Value": "18529"
|
||||
},
|
||||
{
|
||||
"DisplayName": "Op01",
|
||||
"Address": "40001",
|
||||
"Value": "1840"
|
||||
},
|
||||
{
|
||||
"DisplayName": "Op01",
|
||||
"Address": "40002",
|
||||
"Value": "31497"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"CorrelationId": "MessageType1",
|
||||
"SourceTimestamp": "2018-04-17 12:28:50",
|
||||
"Values": [
|
||||
{
|
||||
"DisplayName": "Op02",
|
||||
"Address": "40003",
|
||||
"Value": "21578"
|
||||
},
|
||||
{
|
||||
"DisplayName": "Op02",
|
||||
"Address": "40004",
|
||||
"Value": "26979"
|
||||
},
|
||||
{
|
||||
"DisplayName": "Op01",
|
||||
"Address": "40001",
|
||||
"Value": "13210"
|
||||
},
|
||||
{
|
||||
"DisplayName": "Op01",
|
||||
"Address": "40002",
|
||||
"Value": "13549"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
[
|
||||
{
|
||||
"PublishTimestamp": "2018-04-17 12:28:53",
|
||||
"Content": [
|
||||
{
|
||||
"HwId": "PowerMeter-0a:01:01:01:01:02",
|
||||
"Data": [
|
||||
{
|
||||
"CorrelationId": "MessageType1",
|
||||
"SourceTimestamp": "2018-04-17 12:28:48",
|
||||
"Values": [
|
||||
{
|
||||
"DisplayName": "Op02",
|
||||
"Address": "40003",
|
||||
"Value": "2785"
|
||||
},
|
||||
{
|
||||
"DisplayName": "Op02",
|
||||
"Address": "40004",
|
||||
"Value": "18529"
|
||||
},
|
||||
{
|
||||
"DisplayName": "Op01",
|
||||
"Address": "40001",
|
||||
"Value": "1840"
|
||||
},
|
||||
{
|
||||
"DisplayName": "Op01",
|
||||
"Address": "40002",
|
||||
"Value": "31497"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"CorrelationId": "MessageType1",
|
||||
"SourceTimestamp": "2018-04-17 12:28:50",
|
||||
"Values": [
|
||||
{
|
||||
"DisplayName": "Op02",
|
||||
"Address": "40003",
|
||||
"Value": "21578"
|
||||
},
|
||||
{
|
||||
"DisplayName": "Op02",
|
||||
"Address": "40004",
|
||||
"Value": "26979"
|
||||
},
|
||||
{
|
||||
"DisplayName": "Op01",
|
||||
"Address": "40001",
|
||||
"Value": "13210"
|
||||
},
|
||||
{
|
||||
"DisplayName": "Op01",
|
||||
"Address": "40002",
|
||||
"Value": "13549"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
|
@ -259,6 +236,7 @@ Message Payload:
|
|||
|
||||
### Write to Modbus ###
|
||||
Modbus module use input endpoint "input1" to receive commands. Currently it supports writing back to a single register/cell in a Modbus slave.
|
||||
***Note: Currently IoT Edge only supports send messages into one module from another module, direct C2D messages doesn't work.***
|
||||
|
||||
#### Command Message ####
|
||||
The content of command must be the following message format.
|
||||
|
@ -291,7 +269,7 @@ The command should have a property "command-type" with value "ModbusWrite". Also
|
|||
## HowTo Run ##
|
||||
|
||||
### Run as an IoT Edge module ###
|
||||
Please follow the [link](https://docs.microsoft.com/en-us/azure/iot-edge/tutorial-csharp-module) to deploy the module as an IoT Edge module.
|
||||
Please follow the [TBD-link](https://docs.microsoft.com/en-us/azure/iot-edge/tutorial-csharp-module) to deploy the module as an IoT Edge module.
|
||||
|
||||
#### Configure Modbus RTU ####
|
||||
This is for Modbus RTU only, Modbus TCP could skip this section.
|
||||
|
@ -309,21 +287,4 @@ In the **Container Create Option section**, enter the following for device mappi
|
|||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Debug from Visual Studio 2017 ##
|
||||
Running debug mode requires IoT device connection string being inserted as a environment variable named **EdgeHubConnectionString**, and a local configuration file "iot-edge-modbus.json" since module twin is not available under debug mode. You can copy "iot-edge-modbus.json" template from project root directory to working directory and modify the content to fit your test case.
|
||||
|
||||
**Note**: running in debug mode means none of the IoT Edge features is available. This mode is only to debug non edge-related functions.
|
||||
|
||||
1. Open "iot-edge-modbus.csproj" with **Visual Studio 2017**.
|
||||
2. Open "Program.cs" file in [src](https://github.com/Azure/iot-edge-modbus/tree/master/src) folder.
|
||||
3. Confirm **IOT_EDGE** flag is disabled at first line code.
|
||||
```csharp
|
||||
// #define IOT_EDGE
|
||||
```
|
||||
4. Press **Ctrl+Shift+B** to build project.
|
||||
5. Go to **Project** and select **iot-edge-modbus Properties...**
|
||||
6. Switch to **Debug** tab.
|
||||
7. Add **Environment variables** with **Name** = "EdgeHubConnectionString", and **Value** = "\<your IoT device connection string\>". The connection string can be found from Azure Portal.
|
||||
8. Press F5 to run project.
|
||||
```
|
|
@ -1,57 +0,0 @@
|
|||
{
|
||||
"moduleContent": {
|
||||
"$edgeAgent": {
|
||||
"properties.desired": {
|
||||
"schemaVersion": "1.0",
|
||||
"runtime": {
|
||||
"type": "docker",
|
||||
"settings": {
|
||||
"minDockerVersion": "v1.25",
|
||||
"loggingOptions": ""
|
||||
}
|
||||
},
|
||||
"systemModules": {
|
||||
"edgeAgent": {
|
||||
"type": "docker",
|
||||
"settings": {
|
||||
"image": "microsoft/azureiotedge-agent:1.0-preview",
|
||||
"createOptions": ""
|
||||
}
|
||||
},
|
||||
"edgeHub": {
|
||||
"type": "docker",
|
||||
"status": "running",
|
||||
"restartPolicy": "always",
|
||||
"settings": {
|
||||
"image": "microsoft/azureiotedge-hub:1.0-preview",
|
||||
"createOptions": ""
|
||||
}
|
||||
}
|
||||
},
|
||||
"modules": {
|
||||
"modbus": {
|
||||
"version": "1.0",
|
||||
"type": "docker",
|
||||
"status": "running",
|
||||
"restartPolicy": "always",
|
||||
"settings": {
|
||||
"image": "microsoft/azureiotedge-modbus-tcp:1.0-preview",
|
||||
"createOptions": "{}"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"$edgeHub": {
|
||||
"properties.desired": {
|
||||
"schemaVersion": "1.0",
|
||||
"routes": {
|
||||
"route": "FROM /* INTO $upstream"
|
||||
},
|
||||
"storeAndForwardConfiguration": {
|
||||
"timeToLiveSecs": 7200
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
config/
|
||||
.env
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"name": "iotedgeModbus Remote Debug (.NET Core)",
|
||||
"type": "coreclr",
|
||||
"request": "attach",
|
||||
"processId": "${command:pickRemoteProcess}",
|
||||
"pipeTransport": {
|
||||
"pipeProgram": "docker",
|
||||
"pipeArgs": [
|
||||
"exec",
|
||||
"-i",
|
||||
"modbus",
|
||||
"sh",
|
||||
"-c"
|
||||
],
|
||||
"debuggerPath": "~/vsdbg/vsdbg",
|
||||
"pipeCwd": "${workspaceFolder}",
|
||||
"quoteArgs": true
|
||||
},
|
||||
"sourceFileMap": {
|
||||
"/app": "${workspaceFolder}/modules/iotedgeModbus"
|
||||
},
|
||||
"justMyCode": true
|
||||
}
|
||||
]
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
{
|
||||
"moduleContent": {
|
||||
"$edgeAgent": {
|
||||
"properties.desired": {
|
||||
"schemaVersion": "1.0",
|
||||
"runtime": {
|
||||
"type": "docker",
|
||||
"settings": {
|
||||
"minDockerVersion": "v1.25",
|
||||
"loggingOptions": "",
|
||||
"registryCredentials": {}
|
||||
}
|
||||
},
|
||||
"systemModules": {
|
||||
"edgeAgent": {
|
||||
"type": "docker",
|
||||
"settings": {
|
||||
"image": "mcr.microsoft.com/azureiotedge-agent:1.0",
|
||||
"createOptions": ""
|
||||
}
|
||||
},
|
||||
"edgeHub": {
|
||||
"type": "docker",
|
||||
"status": "running",
|
||||
"restartPolicy": "always",
|
||||
"settings": {
|
||||
"image": "mcr.microsoft.com/azureiotedge-hub:1.0",
|
||||
"createOptions": "{\"HostConfig\":{\"PortBindings\":{\"8883/tcp\":[{\"HostPort\":\"8883\"}],\"443/tcp\":[{\"HostPort\":\"443\"}]}}}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"modules": {
|
||||
"modbus": {
|
||||
"version": "1.0",
|
||||
"type": "docker",
|
||||
"status": "running",
|
||||
"restartPolicy": "always",
|
||||
"settings": {
|
||||
"image": "${MODULES.iotedgeModbus.amd64}",
|
||||
"createOptions": ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"$edgeHub": {
|
||||
"properties.desired": {
|
||||
"schemaVersion": "1.0",
|
||||
"routes": {
|
||||
"iotedgeModbusToIoTHub": "FROM /messages/modules/modbus/outputs/modbusOutput INTO $upstream"
|
||||
},
|
||||
"storeAndForwardConfiguration": {
|
||||
"timeToLiveSecs": 7200
|
||||
}
|
||||
}
|
||||
},
|
||||
"modbus": {
|
||||
"properties.desired":{
|
||||
"PublishInterval": "5000",
|
||||
"SlaveConfigs": {
|
||||
"Slave01": {
|
||||
"SlaveConnection": "<IPV4 address>",
|
||||
"TcpPort": "502",
|
||||
"RetryCount": "10",
|
||||
"RetryInterval": "100",
|
||||
"HwId": "PowerMeter-0a:01:01:01:01:01",
|
||||
"Operations": {
|
||||
"Op01": {
|
||||
"PollingInterval": "2000",
|
||||
"UnitId": "1",
|
||||
"StartAddress": "400001",
|
||||
"Count": "2",
|
||||
"CorrelationId": "MessageType1",
|
||||
"DisplayName": "Voltage"
|
||||
},
|
||||
"Op02": {
|
||||
"PollingInterval": "2000",
|
||||
"UnitId": "1",
|
||||
"StartAddress": "400002",
|
||||
"Count": "2",
|
||||
"CorrelationId": "MessageType2",
|
||||
"DisplayName": "Current"
|
||||
}
|
||||
}
|
||||
},
|
||||
"Slave02": {
|
||||
"SlaveConnection": "<SerialPortName>",
|
||||
"RetryCount": "10",
|
||||
"RetryInterval": "50",
|
||||
"HwId": "PowerMeter-0a:01:01:01:01:02",
|
||||
"BaudRate": "9600",
|
||||
"DataBits": "8",
|
||||
"StopBits": "1",
|
||||
"Parity": "ODD",
|
||||
"FlowControl": "NONE",
|
||||
"Operations": {
|
||||
"Op01": {
|
||||
"PollingInterval": "2000",
|
||||
"UnitId": "1",
|
||||
"StartAddress": "40001",
|
||||
"Count": "2",
|
||||
"DisplayName": "Voltage"
|
||||
},
|
||||
"Op02": {
|
||||
"PollingInterval": "2000",
|
||||
"UnitId": "1",
|
||||
"StartAddress": "40002",
|
||||
"Count": "2",
|
||||
"DisplayName": "Current"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
# .NET Core
|
||||
project.lock.json
|
||||
project.fragment.lock.json
|
||||
artifacts/
|
||||
**/Properties/launchSettings.json
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
.vs
|
||||
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
|
@ -1,29 +1,28 @@
|
|||
FROM microsoft/dotnet:2.0-sdk AS build-env
|
||||
WORKDIR /app
|
||||
|
||||
# copy csproj and restore as distinct layers
|
||||
COPY src/*.cs* ./
|
||||
COPY *.csproj ./
|
||||
RUN dotnet restore
|
||||
|
||||
# build
|
||||
RUN dotnet build
|
||||
RUN dotnet publish -f netcoreapp2.0 -c Release -o out
|
||||
COPY . ./
|
||||
RUN dotnet publish -c Release -o out
|
||||
|
||||
FROM gcc:7 AS build-env-2
|
||||
WORKDIR /app
|
||||
|
||||
# copy .c and .h file
|
||||
COPY src/*.c ./
|
||||
COPY src/*.h ./
|
||||
COPY *.c ./
|
||||
COPY *.h ./
|
||||
|
||||
# build
|
||||
RUN gcc -shared -o libcomWrapper.so -fPIC comWrapper.c
|
||||
|
||||
FROM microsoft/dotnet:2.0.0-runtime
|
||||
|
||||
FROM microsoft/dotnet:2.0-runtime
|
||||
WORKDIR /app
|
||||
|
||||
COPY --from=build-env /app/out ./
|
||||
COPY --from=build-env-2 /app/libcomWrapper.so /usr/lib/
|
||||
|
||||
CMD ["/usr/bin/dotnet", "iot-edge-modbus.dll"]
|
||||
RUN useradd -ms /bin/bash moduleuser
|
||||
USER moduleuser
|
||||
|
||||
ENTRYPOINT ["dotnet", "iotedgeModbus.dll"]
|
|
@ -0,0 +1,35 @@
|
|||
FROM microsoft/dotnet:2.0-runtime-stretch AS base
|
||||
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends unzip procps && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
RUN useradd -ms /bin/bash moduleuser
|
||||
USER moduleuser
|
||||
RUN curl -sSL https://aka.ms/getvsdbgsh | bash /dev/stdin -v latest -l ~/vsdbg
|
||||
|
||||
FROM microsoft/dotnet:2.0-sdk AS build-env
|
||||
WORKDIR /app
|
||||
|
||||
COPY *.csproj ./
|
||||
RUN dotnet restore
|
||||
|
||||
COPY . ./
|
||||
RUN dotnet publish -c Debug -o out
|
||||
|
||||
FROM gcc:7 AS build-env-2
|
||||
WORKDIR /app
|
||||
|
||||
# copy .c and .h file
|
||||
COPY *.c ./
|
||||
COPY *.h ./
|
||||
|
||||
# build
|
||||
RUN gcc -shared -o libcomWrapper.so -fPIC comWrapper.c
|
||||
|
||||
FROM base
|
||||
WORKDIR /app
|
||||
COPY --from=build-env /app/out ./
|
||||
COPY --from=build-env-2 /app/libcomWrapper.so /usr/lib/
|
||||
|
||||
ENTRYPOINT ["dotnet", "iotedgeModbus.dll"]
|
|
@ -0,0 +1,28 @@
|
|||
FROM microsoft/dotnet:2.1-sdk AS build-env
|
||||
WORKDIR /app
|
||||
|
||||
COPY *.csproj ./
|
||||
RUN dotnet restore
|
||||
|
||||
COPY . ./
|
||||
RUN dotnet publish -c Release -o out
|
||||
|
||||
FROM arm32v7/gcc:7 AS build-env-2
|
||||
WORKDIR /app
|
||||
|
||||
# copy .c and .h file
|
||||
COPY *.c ./
|
||||
COPY *.h ./
|
||||
|
||||
# build
|
||||
RUN gcc -shared -o libcomWrapper.so -fPIC comWrapper.c
|
||||
|
||||
FROM microsoft/dotnet:2.1-runtime-stretch-slim-arm32v7
|
||||
WORKDIR /app
|
||||
COPY --from=build-env /app/out ./
|
||||
COPY --from=build-env-2 /app/libcomWrapper.so /usr/lib/
|
||||
|
||||
RUN useradd -ms /bin/bash moduleuser
|
||||
USER moduleuser
|
||||
|
||||
ENTRYPOINT ["dotnet", "iotedgeModbus.dll"]
|
|
@ -0,0 +1,13 @@
|
|||
FROM microsoft/dotnet:2.0-sdk AS build-env
|
||||
WORKDIR /app
|
||||
|
||||
COPY *.csproj ./
|
||||
RUN dotnet restore
|
||||
|
||||
COPY . ./
|
||||
RUN dotnet publish -c Release -o out
|
||||
|
||||
FROM microsoft/dotnet:2.0-runtime
|
||||
WORKDIR /app
|
||||
COPY --from=build-env /app/out ./
|
||||
ENTRYPOINT ["dotnet", "iotedgeModbus.dll"]
|
|
@ -799,7 +799,7 @@
|
|||
{
|
||||
if (IPAddress.TryParse(SlaveConnection, out IPAddress address))
|
||||
return ModbusConstants.ConnectionType.ModbusTCP;
|
||||
else if (SlaveConnection.Substring(0, 3) == "COM" || SlaveConnection.Substring(0, 8) == "/dev/tty")
|
||||
else if (SlaveConnection.Contains("COM") || SlaveConnection.Contains("/tty"))
|
||||
return ModbusConstants.ConnectionType.ModbusRTU;
|
||||
//TODO: ModbusRTU ModbusASCII
|
||||
return ModbusConstants.ConnectionType.Unknown;
|
|
@ -1,5 +1,3 @@
|
|||
#define IOT_EDGE
|
||||
|
||||
namespace Modbus.Containers
|
||||
{
|
||||
using System;
|
||||
|
@ -30,11 +28,6 @@ namespace Modbus.Containers
|
|||
|
||||
static void Main(string[] args)
|
||||
{
|
||||
#if IOT_EDGE
|
||||
// Install CA certificate
|
||||
InstallCert();
|
||||
#endif
|
||||
|
||||
// Initialize Edge Module
|
||||
InitEdgeModule().Wait();
|
||||
|
||||
|
@ -55,37 +48,6 @@ namespace Modbus.Containers
|
|||
return tcs.Task;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add certificate in local cert store for use by client for secure connection to IoT Edge runtime
|
||||
/// </summary>
|
||||
static void InstallCert()
|
||||
{
|
||||
// Suppress cert validation on Windows for now
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string certPath = Environment.GetEnvironmentVariable("EdgeModuleCACertificateFile");
|
||||
if (string.IsNullOrWhiteSpace(certPath))
|
||||
{
|
||||
// We cannot proceed further without a proper cert file
|
||||
Console.WriteLine("Missing path to certificate collection file.");
|
||||
throw new InvalidOperationException("Missing path to certificate file.");
|
||||
}
|
||||
else if (!File.Exists(certPath))
|
||||
{
|
||||
// We cannot proceed further without a proper cert file
|
||||
Console.WriteLine("Missing certificate collection file.");
|
||||
throw new InvalidOperationException("Missing certificate file.");
|
||||
}
|
||||
X509Store store = new X509Store(StoreName.Root, StoreLocation.CurrentUser);
|
||||
store.Open(OpenFlags.ReadWrite);
|
||||
store.Add(new X509Certificate2(X509Certificate2.CreateFromCertFile(certPath)));
|
||||
Console.WriteLine("Added Cert: " + certPath);
|
||||
store.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the Azure IoT Client for the Edge Module
|
||||
/// </summary>
|
||||
|
@ -104,8 +66,7 @@ namespace Modbus.Containers
|
|||
mqttSettings.RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) => true;
|
||||
}
|
||||
ITransportSettings[] settings = { mqttSettings };
|
||||
|
||||
DeviceClient ioTHubModuleClient = DeviceClient.CreateFromConnectionString(connectionString, settings);
|
||||
ModuleClient ioTHubModuleClient = await ModuleClient.CreateFromEnvironmentAsync(settings);
|
||||
await ioTHubModuleClient.OpenAsync();
|
||||
Console.WriteLine("IoT Hub module client initialized.");
|
||||
|
||||
|
@ -176,22 +137,20 @@ namespace Modbus.Containers
|
|||
return MessageResponse.Completed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Callback to handle Twin desired properties updates
|
||||
/// </summary>
|
||||
/// <summary>
|
||||
/// Callback to handle Twin desired properties updates<EFBFBD>
|
||||
/// </summary>
|
||||
static async Task OnDesiredPropertiesUpdate(TwinCollection desiredProperties, object userContext)
|
||||
{
|
||||
DeviceClient ioTHubModuleClient = userContext as DeviceClient;
|
||||
ModuleClient ioTHubModuleClient = userContext as ModuleClient;
|
||||
|
||||
try
|
||||
{
|
||||
#if IOT_EDGE
|
||||
// stop all activities while updating configuration
|
||||
await ioTHubModuleClient.SetInputMessageHandlerAsync(
|
||||
"input1",
|
||||
DummyCallBack,
|
||||
null);
|
||||
#endif
|
||||
|
||||
m_run = false;
|
||||
await Task.WhenAll(m_task_list);
|
||||
|
@ -230,7 +189,7 @@ namespace Modbus.Containers
|
|||
/// <summary>
|
||||
/// Update Start from module Twin.
|
||||
/// </summary>
|
||||
static async Task UpdateStartFromTwin(TwinCollection desiredProperties, DeviceClient ioTHubModuleClient)
|
||||
static async Task UpdateStartFromTwin(TwinCollection desiredProperties, ModuleClient ioTHubModuleClient)
|
||||
{
|
||||
ModuleConfig config;
|
||||
Slaves.ModuleHandle moduleHandle;
|
||||
|
@ -284,16 +243,12 @@ namespace Modbus.Containers
|
|||
|
||||
if (moduleHandle != null)
|
||||
{
|
||||
var userContext = new Tuple<DeviceClient, Slaves.ModuleHandle>(ioTHubModuleClient, moduleHandle);
|
||||
#if IOT_EDGE
|
||||
// Register callback to be called when a message is received by the module
|
||||
await ioTHubModuleClient.SetInputMessageHandlerAsync(
|
||||
"input1",
|
||||
PipeMessage,
|
||||
userContext);
|
||||
#else
|
||||
m_task_list.Add(Receive(userContext));
|
||||
#endif
|
||||
var userContext = new Tuple<ModuleClient, Slaves.ModuleHandle>(ioTHubModuleClient, moduleHandle);
|
||||
// Register callback to be called when a message is received by the module
|
||||
await ioTHubModuleClient.SetInputMessageHandlerAsync(
|
||||
"input1",
|
||||
PipeMessage,
|
||||
userContext);
|
||||
m_task_list.Add(Start(userContext));
|
||||
}
|
||||
}
|
||||
|
@ -307,14 +262,13 @@ namespace Modbus.Containers
|
|||
/// <returns></returns>
|
||||
static async Task Start(object userContext)
|
||||
{
|
||||
var userContextValues = userContext as Tuple<DeviceClient, Slaves.ModuleHandle>;
|
||||
var userContextValues = userContext as Tuple<ModuleClient, Slaves.ModuleHandle>;
|
||||
if (userContextValues == null)
|
||||
{
|
||||
throw new InvalidOperationException("UserContext doesn't contain " +
|
||||
"expected values");
|
||||
}
|
||||
|
||||
DeviceClient ioTHubModuleClient = userContextValues.Item1;
|
||||
ModuleClient ioTHubModuleClient = userContextValues.Item1;
|
||||
Slaves.ModuleHandle moduleHandle = userContextValues.Item2;
|
||||
|
||||
foreach (ModbusSlaveSession s in moduleHandle.ModbusSessionList)
|
||||
|
@ -342,11 +296,7 @@ namespace Modbus.Containers
|
|||
|
||||
if (message != null)
|
||||
{
|
||||
#if IOT_EDGE
|
||||
await ioTHubModuleClient.SendEventAsync("modbusOutput", message);
|
||||
#else
|
||||
await ioTHubModuleClient.SendEventAsync(message);
|
||||
#endif
|
||||
}
|
||||
if (!m_run)
|
||||
{
|
||||
|
@ -356,40 +306,5 @@ namespace Modbus.Containers
|
|||
}
|
||||
moduleHandle.Release();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Receive C2D message(running without iot edge)
|
||||
/// </summary>
|
||||
/// <param name="userContext"></param>
|
||||
/// <returns></returns>
|
||||
static async Task Receive(object userContext)
|
||||
{
|
||||
var userContextValues = userContext as Tuple<DeviceClient, Slaves.ModuleHandle>;
|
||||
if (userContextValues == null)
|
||||
{
|
||||
throw new InvalidOperationException("UserContext doesn't contain " +
|
||||
"expected values");
|
||||
}
|
||||
DeviceClient ioTHubModuleClient = userContextValues.Item1;
|
||||
var timeout = TimeSpan.FromSeconds(3);
|
||||
while (m_run)
|
||||
{
|
||||
try
|
||||
{
|
||||
Message message = await ioTHubModuleClient.ReceiveAsync(timeout);
|
||||
if (message != null)
|
||||
{
|
||||
await PipeMessage(message, userContext);
|
||||
await ioTHubModuleClient.CompleteAsync(message);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Console.WriteLine();
|
||||
Console.WriteLine("Error when receiving: {0}", ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -57,6 +57,7 @@ namespace tempSerialPort
|
|||
{
|
||||
this.serialPort.Open();
|
||||
this.serialPort.Handshake = Handshake.None;
|
||||
this.serialPort.ReadTimeout = 5000;
|
||||
}
|
||||
|
||||
private WinSerialDevice(string portName, int baudRate, Parity parity, int dataBits, StopBits stopBits)
|
|
@ -2,36 +2,22 @@
|
|||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<RootNamespace>Modbus.Containers</RootNamespace>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Release|netcoreapp2.0|AnyCPU'">
|
||||
<PropertyGroup Condition="'$(Configuration)|$(TargetFramework)|$(Platform)'=='Debug|netcoreapp2.0|AnyCPU'">
|
||||
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
|
||||
<TreatSpecificWarningsAsErrors />
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<DefineConstants>DEBUG;TRACE;NETCOREAPP2_0</DefineConstants>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="V1\**" />
|
||||
<EmbeddedResource Remove="V1\**" />
|
||||
<None Remove="V1\**" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Azure.Devices.Client" Version="1.6.0-preview-001" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.0-preview2-final" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="2.0.0-preview2-final" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.0.0-preview2-final" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0-preview2-final" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0-preview2-final" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0-preview2-final" />
|
||||
<PackageReference Include="Microsoft.Azure.Devices.Client" Version="1.17.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Abstractions" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Binder" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.EnvironmentVariables" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.FileExtensions" Version="2.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.Json" Version="2.0.0" />
|
||||
<PackageReference Include="System.Runtime.Loader" Version="4.3.0" />
|
||||
<PackageReference Include="System.IO.Ports" Version="4.4" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
</Project>
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"$schema-version": "0.0.1",
|
||||
"description": "",
|
||||
"image": {
|
||||
"repository": "localhost:5000/iotedgemodbus",
|
||||
"tag": {
|
||||
"version": "0.0.1",
|
||||
"platforms": {
|
||||
"amd64": "./Dockerfile.amd64",
|
||||
"amd64.debug": "./Dockerfile.amd64.debug",
|
||||
"arm32v7": "./Dockerfile.arm32v7",
|
||||
"windows-amd64": "./Dockerfile.windows-amd64"
|
||||
}
|
||||
},
|
||||
"buildOptions": []
|
||||
},
|
||||
"language": "csharp"
|
||||
}
|
Загрузка…
Ссылка в новой задаче