├── .DS_Store
├── Blockchain
├── .DS_Store
├── IoT-Perishable-Network
│ ├── README.md
│ ├── lib
│ │ └── logic.js
│ ├── logic.js
│ ├── models
│ │ └── perishable.cto
│ ├── package.json
│ ├── perishable.cto
│ └── permissions.acl
├── README-ja.md
├── README.md
├── iot-asset-tracker-network.bna
└── screenshots
│ ├── .DS_Store
│ ├── API.png
│ ├── Authorize.png
│ ├── AuthorizeCloud.png
│ ├── Breadcrumbs.png
│ ├── ConnectNow.png
│ ├── Create.png
│ ├── DeliveryPipeline.png
│ ├── DeployMarbles.png
│ ├── DeploymentProgress.png
│ ├── DevOps.png
│ ├── Guided.png
│ ├── MarblesToolchain.png
│ ├── MarblesUI.png
│ ├── Passed.png
│ ├── Perishable-Network-BNA-ConnectNow.png
│ ├── Perishable-Network-BNA-Model-update-annotated.png
│ ├── Perishable-Network-BNA-annotated.png
│ ├── Perishable-Network-BNA-creds-annotated.png
│ ├── Perishable-Network-REST-API-swagger.png
│ ├── RepoName.png
│ ├── SeeApp.png
│ ├── SelectGitHub.png
│ ├── SetupDemo.png
│ ├── SubmitTransaction.png
│ ├── Success.png
│ ├── Test.png
│ ├── ToolChainName.png
│ ├── TrySamples.png
│ ├── Update.png
│ ├── ViewLogs.png
│ ├── VisitAppURL.png
│ ├── clonegithub.png
│ ├── completetoolchain.png
│ ├── composer-rest-server.png
│ ├── deploynew.png
│ ├── deploypassed.png
│ ├── developcode.png
│ ├── example.png
│ ├── export.png
│ ├── gitcommit.png
│ ├── gotogithub.png
│ ├── launchnow.png
│ ├── menubar.png
│ ├── movecontents.png
│ ├── npmsample.png
│ ├── repositorycreate.png
│ ├── restserverdetails.png
│ ├── savebna.png
│ ├── starterkittoolchain.png
│ ├── toolchainlog.png
│ ├── webplayground.png
│ └── yo.png
├── LICENSE
├── Node-RED
├── README-ja.md
├── README.md
├── flows
│ └── IoTAssetTracker-AllFlows.json
└── screenshots
│ ├── IBMCloud-Catalog-newstarter-annotated.png
│ ├── IBMCloud-NodeRED-CFappcreate.png
│ ├── IBMCloud-NodeRED-import.png
│ ├── IBMCloud-NodeRED-launch.png
│ ├── IBMCloud-NodeRED-nodeinstall.png
│ ├── IBMCloud-NodeRED-palette.png
│ ├── IBMCloud-NodeRED-pastefromclipboard.png
│ ├── Node-RED-dashboard-AssetTracker-NJ.png
│ ├── Node-RED-dashboard-AssetTracker-PR.png
│ ├── Node-RED-dashboard-ControlParticleDevice.png
│ ├── Node-RED-flow-AssetTrackerDashboardControls.png
│ ├── Node-RED-flow-AssetTrackerMap.png
│ ├── Node-RED-flow-ControlParticleDevice.png
│ ├── Node-RED-flow-InitPerishableBlockchain.png
│ ├── Node-RED-flow-LoadBlockchainTransactionHistory.png
│ ├── Node-RED-flow-ReceiveParticleEvents.png
│ └── Node-RED-flow-WriteParticleEvents2Blockchain.png
├── ParticleElectron
├── README-ja.md
├── README.md
├── WatsonIoTAssetTracker.ino
├── project.properties
└── screenshots
│ ├── ParticleConsoleDeviceEvents.png
│ ├── ParticleElectronAssetTracker-IoT.jpg
│ ├── ParticleElectronAssetTracker-Kit.jpg
│ └── ParticleElectronAssetTracker-in-Case.jpg
├── README-ja.md
├── README.md
└── Workshop
├── README-ja.md
└── README.md
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/.DS_Store
--------------------------------------------------------------------------------
/Blockchain/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/.DS_Store
--------------------------------------------------------------------------------
/Blockchain/IoT-Perishable-Network/README.md:
--------------------------------------------------------------------------------
1 | # IoT Asset Tracking Perishable Goods Network
2 |
3 | > Example business network that shows growers, shippers and importers defining contracts for the price of perishable goods, based on temperature readings from IoT sensors in the shipping containers.
4 |
5 | The business network defines a contract between growers and importers. The contract stipulates that: On receipt of the shipment the importer pays the grower the unit price x the number of units in the shipment. Shipments that arrive late are free. Shipments that have breached the low temperate threshold have a penalty applied proportional to the magnitude of the breach x a penalty factor. Shipments that have breached the high temperate threshold have a penalty applied proportional to the magnitude of the breach x a penalty factor.
6 |
7 | This business network defines:
8 |
9 | **Participants**
10 | `Grower` `Importer` `Shipper`
11 |
12 | **Assets**
13 | `Contract` `Shipment`
14 |
15 | **Transactions**
16 | `TemperatureReading``AccelReading` `GpsReading` `ShipmentReceived` `SetupDemo`
17 |
18 | **Events**
19 | `TemperatureThresholdEvent` `AccelerationThresholdEvent` `ShipmentInPortEvent`
20 |
21 | To test this Business Network Definition in the **Test** tab:
22 |
23 | Submit a `SetupDemo` transaction:
24 |
25 | ```
26 | {
27 | "$class": "org.acme.shipping.perishable.SetupDemo"
28 | }
29 | ```
30 |
31 | This transaction populates the Participant Registries with a `Grower`, an `Importer` and a `Shipper`. The Asset Registries will have a `Contract` asset and a `Shipment` asset.
32 |
33 | Submit a `TemperatureReading` transaction:
34 |
35 | ```
36 | {
37 | "$class": "org.acme.shipping.perishable.TemperatureReading",
38 | "celsius": 8,
39 | "latitude": "40.6840",
40 | "longitude":"74.0062",
41 | "readingTime": "2018-03-22T17:31:36.229Z",
42 | "shipment": "resource:org.acme.shipping.perishable.Shipment#SHIP_001"
43 | }
44 | ```
45 |
46 | If the temperature reading falls outside the min/max range of the contract, the price received by the grower will be reduced, and a `TemperatureThresholdEvent` is emitted. You may submit several readings if you wish. Each reading will be aggregated within `SHIP_001` Shipment Asset Registry.
47 |
48 | Submit a `AccelReading` transaction:
49 |
50 | ```
51 | {
52 | "$class": "org.acme.shipping.perishable.AccelReading",
53 | "accel_x": -96,
54 | "accel_y": 18368,
55 | "accel_z": -12032,
56 | "latitude": "40.6840",
57 | "longitude":"74.0062",
58 | "readingTime": "2018-03-22T17:31:36.229Z",
59 | "shipment": "resource:org.acme.shipping.perishable.Shipment#SHIP_001"
60 | }
61 | ```
62 |
63 | If the acceleration reading falls outside the min/max range of the contract, the price received by the grower will be reduced, and a `AccelerationThresholdEvent` is emitted. You may submit several readings if you wish. Each reading will be aggregated within `SHIP_001` Shipment Asset Registry.
64 |
65 | Submit a `ShipmentReceived` transaction for `SHIP_001` to trigger the payout to the grower, based on the parameters of the `CON_001` contract:
66 |
67 | ```
68 | {
69 | "$class": "org.acme.shipping.perishable.ShipmentReceived",
70 | "shipment": "resource:org.acme.shipping.perishable.Shipment#SHIP_001"
71 | }
72 | ```
73 |
74 | If the date-time of the `ShipmentReceived` transaction is after the `arrivalDateTime` on `CON_001` then the grower will no receive any payment for the shipment.
75 |
76 | Submit a `GpsReading` transaction:
77 |
78 | ```
79 | {
80 | "$class": "org.acme.shipping.perishable.GpsReading",
81 | "readingTime": "120000",
82 | "readingDate": "20171024",
83 | "latitude":"40.6840",
84 | "latitudeDir":"N",
85 | "longitude":"74.0062",
86 | "laongitudeDir":"W",
87 | }
88 | ```
89 |
90 | If the GPS reading indicates the ship's location is the Port of New Jersey/New York (40.6840,-74.0062) then a `ShipmentInPortEvent` is emitted.
91 |
92 | Enjoy!
93 |
--------------------------------------------------------------------------------
/Blockchain/IoT-Perishable-Network/lib/logic.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | /**
16 | * A shipment has been received by an importer
17 | * @param {org.acme.shipping.perishable.ShipmentReceived} shipmentReceived - the ShipmentReceived transaction
18 | * @transaction
19 | */
20 | function payOut(shipmentReceived) {
21 |
22 | var contract = shipmentReceived.shipment.contract;
23 | var shipment = shipmentReceived.shipment;
24 | var payOut = contract.unitPrice * shipment.unitCount;
25 |
26 | //console.log('Received at: ' + shipmentReceived.timestamp);
27 | //console.log('Contract arrivalDateTime: ' + contract.arrivalDateTime);
28 |
29 | // set the status of the shipment
30 | shipment.status = 'ARRIVED';
31 |
32 | // if the shipment did not arrive on time the payout is zero
33 | if (shipmentReceived.timestamp > contract.arrivalDateTime) {
34 | payOut = 0;
35 | //console.log('Late shipment');
36 | } else {
37 | // find the lowest temperature reading
38 | if (shipment.temperatureReadings) {
39 | // sort the temperatureReadings by celsius
40 | shipment.temperatureReadings.sort(function (a, b) {
41 | return (a.celsius - b.celsius);
42 | });
43 | var lowestReading = shipment.temperatureReadings[0];
44 | var highestReading = shipment.temperatureReadings[shipment.temperatureReadings.length - 1];
45 | var penalty = 0;
46 | //console.log('Lowest temp reading: ' + lowestReading.celsius);
47 | //console.log('Highest temp reading: ' + highestReading.celsius);
48 |
49 | // does the lowest temperature violate the contract?
50 | if (lowestReading.celsius < contract.minTemperature) {
51 | penalty += (contract.minTemperature - lowestReading.celsius) * contract.minPenaltyFactor;
52 | //console.log('Min temp penalty: ' + penalty);
53 | }
54 |
55 | // does the highest temperature violate the contract?
56 | if (highestReading.celsius > contract.maxTemperature) {
57 | penalty += (highestReading.celsius - contract.maxTemperature) * contract.maxPenaltyFactor;
58 | //console.log('Max temp penalty: ' + penalty);
59 | }
60 |
61 | // apply any penalities
62 | payOut -= (penalty * shipment.unitCount);
63 |
64 | if (payOut < 0) {
65 | payOut = 0;
66 | }
67 | }
68 | }
69 |
70 | //console.log('Payout: ' + payOut);
71 | contract.grower.accountBalance += payOut;
72 | contract.importer.accountBalance -= payOut;
73 |
74 | //console.log('Grower: ' + contract.grower.$identifier + ' new balance: ' + contract.grower.accountBalance);
75 | //console.log('Importer: ' + contract.importer.$identifier + ' new balance: ' + contract.importer.accountBalance);
76 |
77 | return getParticipantRegistry('org.acme.shipping.perishable.Grower')
78 | .then(function (growerRegistry) {
79 | // update the grower's balance
80 | return growerRegistry.update(contract.grower);
81 | })
82 | .then(function () {
83 | return getParticipantRegistry('org.acme.shipping.perishable.Importer');
84 | })
85 | .then(function (importerRegistry) {
86 | // update the importer's balance
87 | return importerRegistry.update(contract.importer);
88 | })
89 | .then(function () {
90 | return getAssetRegistry('org.acme.shipping.perishable.Shipment');
91 | })
92 | .then(function (shipmentRegistry) {
93 | // update the state of the shipment
94 | return shipmentRegistry.update(shipment);
95 | });
96 | }
97 |
98 | /**
99 | * A temperature reading has been received for a shipment
100 | * @param {org.acme.shipping.perishable.TemperatureReading} temperatureReading - the TemperatureReading transaction
101 | * @transaction
102 | */
103 | function temperatureReading(temperatureReading) {
104 |
105 | var shipment = temperatureReading.shipment;
106 | var NS = 'org.acme.shipping.perishable';
107 | var contract = shipment.contract;
108 | var factory = getFactory();
109 |
110 | //console.log('Adding temperature ' + temperatureReading.celsius + ' to shipment ' + shipment.$identifier);
111 |
112 | if (shipment.temperatureReadings) {
113 | shipment.temperatureReadings.push(temperatureReading);
114 | } else {
115 | shipment.temperatureReadings = [temperatureReading];
116 | }
117 |
118 | if (temperatureReading.celsius < contract.minTemperature ||
119 | temperatureReading.celsius > contract.maxTemperature) {
120 | var temperatureEvent = factory.newEvent(NS, 'TemperatureThresholdEvent');
121 | temperatureEvent.shipment = shipment;
122 | temperatureEvent.temperature = temperatureReading.celsius;
123 | temperatureEvent.latitude = temperatureReading.latitude;
124 | temperatureEvent.longitude = temperatureReading.longitude;
125 | temperatureEvent.readingTime = temperatureReading.readingTime;
126 | temperatureEvent.message = 'Temperature threshold violated! Emitting TemperatureEvent for shipment: ' + shipment.$identifier;
127 | emit(temperatureEvent);
128 | }
129 |
130 | return getAssetRegistry(NS + '.Shipment')
131 | .then(function (shipmentRegistry) {
132 | // add the temp reading to the shipment
133 | return shipmentRegistry.update(shipment);
134 | });
135 | }
136 |
137 | /**
138 | * An Acceleration reading has been received for a shipment
139 | * @param {org.acme.shipping.perishable.AccelReading} AccelReading - the AccelReading transaction
140 | * @transaction
141 | */
142 | function AccelReading(AccelReading) {
143 | var shipment = AccelReading.shipment;
144 | var NS = 'org.acme.shipping.perishable';
145 | var contract = shipment.contract;
146 | var factory = getFactory();
147 |
148 | //console.log('Adding acceleration ' + AccelReading.accel_x + ' to shipment ' + shipment.$identifier);
149 |
150 | if (shipment.AccelReadings) {
151 | shipment.AccelReadings.push(AccelReading);
152 | } else {
153 | shipment.AccelReadings = [AccelReading];
154 | }
155 |
156 | // Also test for accel_y / accel_z
157 | if (AccelReading.accel_x < contract.maxAccel ) {
158 | var AccelerationEvent = factory.newEvent(NS, 'AccelerationThresholdEvent');
159 | AccelerationEvent.shipment = shipment;
160 | AccelerationEvent.accel_x = AccelReading.accel_x;
161 | AccelerationEvent.accel_y = AccelReading.accel_y;
162 | AccelerationEvent.accel_z = AccelReading.accel_z;
163 | AccelerationEvent.latitude = AccelReading.latitude;
164 | AccelerationEvent.longitude = AccelReading.longitude;
165 | AccelerationEvent.readingTime = AccelReading.readingTime;
166 | AccelerationEvent.message = 'Acceleration threshold violated! Emitting AccelerationEvent for shipment: ' + shipment.$identifier;
167 | emit(AccelerationEvent);
168 | }
169 |
170 | return getAssetRegistry(NS + '.Shipment')
171 | .then(function (shipmentRegistry) {
172 | // add the temp reading to the shipment
173 | return shipmentRegistry.update(shipment);
174 | });
175 | }
176 |
177 | /**
178 | * A GPS reading has been received for a shipment
179 | * @param {org.acme.shipping.perishable.GpsReading} gpsReading - the GpsReading transaction
180 | * @transaction
181 | */
182 | function gpsReading(gpsReading) {
183 |
184 | var factory = getFactory();
185 | var NS = "org.acme.shipping.perishable";
186 | var shipment = gpsReading.shipment;
187 | var PORT_OF_NEW_YORK = '/LAT:40.6840N/LONG:74.0062W';
188 |
189 | if (shipment.gpsReadings) {
190 | shipment.gpsReadings.push(gpsReading);
191 | } else {
192 | shipment.gpsReadings = [gpsReading];
193 | }
194 |
195 | var latLong = '/LAT:' + gpsReading.latitude + gpsReading.latitudeDir + '/LONG:' +
196 | gpsReading.longitude + gpsReading.longitudeDir;
197 |
198 | if (latLong == PORT_OF_NEW_YORK) {
199 | var shipmentInPortEvent = factory.newEvent(NS, 'ShipmentInPortEvent');
200 | shipmentInPortEvent.shipment = shipment;
201 | var message = 'Shipment has reached the destination port of ' + PORT_OF_NEW_YORK;
202 | shipmentInPortEvent.message = message;
203 | emit(shipmentInPortEvent);
204 | }
205 |
206 | return getAssetRegistry(NS + '.Shipment')
207 | .then(function (shipmentRegistry) {
208 | // add the temp reading to the shipment
209 | return shipmentRegistry.update(shipment);
210 | });
211 | }
212 |
213 | /**
214 | * Initialize some test assets and participants useful for running a demo.
215 | * @param {org.acme.shipping.perishable.SetupDemo} setupDemo - the SetupDemo transaction
216 | * @transaction
217 | */
218 | function setupDemo(setupDemo) {
219 |
220 | var factory = getFactory();
221 | var NS = 'org.acme.shipping.perishable';
222 |
223 | // create the grower
224 | var grower = factory.newResource(NS, 'Grower', 'farmer@email.com');
225 | var growerAddress = factory.newConcept(NS, 'Address');
226 | growerAddress.country = 'USA';
227 | grower.address = growerAddress;
228 | grower.accountBalance = 0;
229 |
230 | // create the importer
231 | var importer = factory.newResource(NS, 'Importer', 'supermarket@email.com');
232 | var importerAddress = factory.newConcept(NS, 'Address');
233 | importerAddress.country = 'UK';
234 | importer.address = importerAddress;
235 | importer.accountBalance = 0;
236 |
237 | // create the shipper
238 | var shipper = factory.newResource(NS, 'Shipper', 'shipper@email.com');
239 | var shipperAddress = factory.newConcept(NS, 'Address');
240 | shipperAddress.country = 'Panama';
241 | shipper.address = shipperAddress;
242 | shipper.accountBalance = 0;
243 |
244 | // create the contract
245 | var contract = factory.newResource(NS, 'Contract', 'CON_002');
246 | contract.grower = factory.newRelationship(NS, 'Grower', 'farmer@email.com');
247 | contract.importer = factory.newRelationship(NS, 'Importer', 'supermarket@email.com');
248 | contract.shipper = factory.newRelationship(NS, 'Shipper', 'shipper@email.com');
249 | var tomorrow = setupDemo.timestamp;
250 | tomorrow.setDate(tomorrow.getDate() + 1);
251 | contract.arrivalDateTime = tomorrow; // the shipment has to arrive tomorrow
252 | contract.unitPrice = 0.5; // pay 50 cents per unit
253 | contract.minTemperature = 2; // min temperature for the cargo
254 | contract.maxTemperature = 10; // max temperature for the cargo
255 | contract.maxAccel = 15000; // max acceleration for the cargo
256 | contract.minPenaltyFactor = 0.2; // we reduce the price by 20 cents for every degree below the min temp
257 | contract.maxPenaltyFactor = 0.1; // we reduce the price by 10 cents for every degree above the max temp
258 |
259 | // create the shipment
260 | var shipment = factory.newResource(NS, 'Shipment', '320022000251363131363432');
261 | shipment.type = 'MEDICINE';
262 | shipment.status = 'IN_TRANSIT';
263 | shipment.unitCount = 5000;
264 | shipment.contract = factory.newRelationship(NS, 'Contract', 'CON_002');
265 | return getParticipantRegistry(NS + '.Grower')
266 | .then(function (growerRegistry) {
267 | // add the growers
268 | return growerRegistry.addAll([grower]);
269 | })
270 | .then(function() {
271 | return getParticipantRegistry(NS + '.Importer');
272 | })
273 | .then(function(importerRegistry) {
274 | // add the importers
275 | return importerRegistry.addAll([importer]);
276 | })
277 | .then(function() {
278 | return getParticipantRegistry(NS + '.Shipper');
279 | })
280 | .then(function(shipperRegistry) {
281 | // add the shippers
282 | return shipperRegistry.addAll([shipper]);
283 | })
284 | .then(function() {
285 | return getAssetRegistry(NS + '.Contract');
286 | })
287 | .then(function(contractRegistry) {
288 | // add the contracts
289 | return contractRegistry.addAll([contract]);
290 | })
291 | .then(function() {
292 | return getAssetRegistry(NS + '.Shipment');
293 | })
294 | .then(function(shipmentRegistry) {
295 | // add the shipments
296 | return shipmentRegistry.addAll([shipment]);
297 | });
298 | }
--------------------------------------------------------------------------------
/Blockchain/IoT-Perishable-Network/logic.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Licensed under the Apache License, Version 2.0 (the "License");
3 | * you may not use this file except in compliance with the License.
4 | * You may obtain a copy of the License at
5 | *
6 | * http://www.apache.org/licenses/LICENSE-2.0
7 | *
8 | * Unless required by applicable law or agreed to in writing, software
9 | * distributed under the License is distributed on an "AS IS" BASIS,
10 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 | * See the License for the specific language governing permissions and
12 | * limitations under the License.
13 | */
14 |
15 | /**
16 | * A shipment has been received by an importer
17 | * @param {org.acme.shipping.perishable.ShipmentReceived} shipmentReceived - the ShipmentReceived transaction
18 | * @transaction
19 | */
20 | function payOut(shipmentReceived) {
21 |
22 | var contract = shipmentReceived.shipment.contract;
23 | var shipment = shipmentReceived.shipment;
24 | var payOut = contract.unitPrice * shipment.unitCount;
25 |
26 | //console.log('Received at: ' + shipmentReceived.timestamp);
27 | //console.log('Contract arrivalDateTime: ' + contract.arrivalDateTime);
28 |
29 | // set the status of the shipment
30 | shipment.status = 'ARRIVED';
31 |
32 | // if the shipment did not arrive on time the payout is zero
33 | if (shipmentReceived.timestamp > contract.arrivalDateTime) {
34 | payOut = 0;
35 | //console.log('Late shipment');
36 | } else {
37 | // find the lowest temperature reading
38 | if (shipment.temperatureReadings) {
39 | // sort the temperatureReadings by celsius
40 | shipment.temperatureReadings.sort(function (a, b) {
41 | return (a.celsius - b.celsius);
42 | });
43 | var lowestReading = shipment.temperatureReadings[0];
44 | var highestReading = shipment.temperatureReadings[shipment.temperatureReadings.length - 1];
45 | var penalty = 0;
46 | //console.log('Lowest temp reading: ' + lowestReading.celsius);
47 | //console.log('Highest temp reading: ' + highestReading.celsius);
48 |
49 | // does the lowest temperature violate the contract?
50 | if (lowestReading.celsius < contract.minTemperature) {
51 | penalty += (contract.minTemperature - lowestReading.celsius) * contract.minPenaltyFactor;
52 | //console.log('Min temp penalty: ' + penalty);
53 | }
54 |
55 | // does the highest temperature violate the contract?
56 | if (highestReading.celsius > contract.maxTemperature) {
57 | penalty += (highestReading.celsius - contract.maxTemperature) * contract.maxPenaltyFactor;
58 | //console.log('Max temp penalty: ' + penalty);
59 | }
60 |
61 | // apply any penalities
62 | payOut -= (penalty * shipment.unitCount);
63 |
64 | if (payOut < 0) {
65 | payOut = 0;
66 | }
67 | }
68 | }
69 |
70 | //console.log('Payout: ' + payOut);
71 | contract.grower.accountBalance += payOut;
72 | contract.importer.accountBalance -= payOut;
73 |
74 | //console.log('Grower: ' + contract.grower.$identifier + ' new balance: ' + contract.grower.accountBalance);
75 | //console.log('Importer: ' + contract.importer.$identifier + ' new balance: ' + contract.importer.accountBalance);
76 |
77 | return getParticipantRegistry('org.acme.shipping.perishable.Grower')
78 | .then(function (growerRegistry) {
79 | // update the grower's balance
80 | return growerRegistry.update(contract.grower);
81 | })
82 | .then(function () {
83 | return getParticipantRegistry('org.acme.shipping.perishable.Importer');
84 | })
85 | .then(function (importerRegistry) {
86 | // update the importer's balance
87 | return importerRegistry.update(contract.importer);
88 | })
89 | .then(function () {
90 | return getAssetRegistry('org.acme.shipping.perishable.Shipment');
91 | })
92 | .then(function (shipmentRegistry) {
93 | // update the state of the shipment
94 | return shipmentRegistry.update(shipment);
95 | });
96 | }
97 |
98 | /**
99 | * A temperature reading has been received for a shipment
100 | * @param {org.acme.shipping.perishable.TemperatureReading} temperatureReading - the TemperatureReading transaction
101 | * @transaction
102 | */
103 | function temperatureReading(temperatureReading) {
104 |
105 | var shipment = temperatureReading.shipment;
106 | var NS = 'org.acme.shipping.perishable';
107 | var contract = shipment.contract;
108 | var factory = getFactory();
109 |
110 | //console.log('Adding temperature ' + temperatureReading.celsius + ' to shipment ' + shipment.$identifier);
111 |
112 | if (shipment.temperatureReadings) {
113 | shipment.temperatureReadings.push(temperatureReading);
114 | } else {
115 | shipment.temperatureReadings = [temperatureReading];
116 | }
117 |
118 | if (temperatureReading.celsius < contract.minTemperature ||
119 | temperatureReading.celsius > contract.maxTemperature) {
120 | var temperatureEvent = factory.newEvent(NS, 'TemperatureThresholdEvent');
121 | temperatureEvent.shipment = shipment;
122 | temperatureEvent.temperature = temperatureReading.celsius;
123 | temperatureEvent.latitude = temperatureReading.latitude;
124 | temperatureEvent.longitude = temperatureReading.longitude;
125 | temperatureEvent.readingTime = temperatureReading.readingTime;
126 | temperatureEvent.message = 'Temperature threshold violated! Emitting TemperatureEvent for shipment: ' + shipment.$identifier;
127 | emit(temperatureEvent);
128 | }
129 |
130 | return getAssetRegistry(NS + '.Shipment')
131 | .then(function (shipmentRegistry) {
132 | // add the temp reading to the shipment
133 | return shipmentRegistry.update(shipment);
134 | });
135 | }
136 |
137 | /**
138 | * An Acceleration reading has been received for a shipment
139 | * @param {org.acme.shipping.perishable.AccelReading} AccelReading - the AccelReading transaction
140 | * @transaction
141 | */
142 | function AccelReading(AccelReading) {
143 | var shipment = AccelReading.shipment;
144 | var NS = 'org.acme.shipping.perishable';
145 | var contract = shipment.contract;
146 | var factory = getFactory();
147 |
148 | //console.log('Adding acceleration ' + AccelReading.accel_x + ' to shipment ' + shipment.$identifier);
149 |
150 | if (shipment.AccelReadings) {
151 | shipment.AccelReadings.push(AccelReading);
152 | } else {
153 | shipment.AccelReadings = [AccelReading];
154 | }
155 |
156 | // Also test for accel_y / accel_z
157 | if (AccelReading.accel_x < contract.maxAccel ) {
158 | var AccelerationEvent = factory.newEvent(NS, 'AccelerationThresholdEvent');
159 | AccelerationEvent.shipment = shipment;
160 | AccelerationEvent.accel_x = AccelReading.accel_x;
161 | AccelerationEvent.accel_y = AccelReading.accel_y;
162 | AccelerationEvent.accel_z = AccelReading.accel_z;
163 | AccelerationEvent.latitude = AccelReading.latitude;
164 | AccelerationEvent.longitude = AccelReading.longitude;
165 | AccelerationEvent.readingTime = AccelReading.readingTime;
166 | AccelerationEvent.message = 'Acceleration threshold violated! Emitting AccelerationEvent for shipment: ' + shipment.$identifier;
167 | emit(AccelerationEvent);
168 | }
169 |
170 | return getAssetRegistry(NS + '.Shipment')
171 | .then(function (shipmentRegistry) {
172 | // add the temp reading to the shipment
173 | return shipmentRegistry.update(shipment);
174 | });
175 | }
176 |
177 | /**
178 | * A GPS reading has been received for a shipment
179 | * @param {org.acme.shipping.perishable.GpsReading} gpsReading - the GpsReading transaction
180 | * @transaction
181 | */
182 | function gpsReading(gpsReading) {
183 |
184 | var factory = getFactory();
185 | var NS = "org.acme.shipping.perishable";
186 | var shipment = gpsReading.shipment;
187 | var PORT_OF_NEW_YORK = '/LAT:40.6840N/LONG:74.0062W';
188 |
189 | if (shipment.gpsReadings) {
190 | shipment.gpsReadings.push(gpsReading);
191 | } else {
192 | shipment.gpsReadings = [gpsReading];
193 | }
194 |
195 | var latLong = '/LAT:' + gpsReading.latitude + gpsReading.latitudeDir + '/LONG:' +
196 | gpsReading.longitude + gpsReading.longitudeDir;
197 |
198 | if (latLong == PORT_OF_NEW_YORK) {
199 | var shipmentInPortEvent = factory.newEvent(NS, 'ShipmentInPortEvent');
200 | shipmentInPortEvent.shipment = shipment;
201 | var message = 'Shipment has reached the destination port of ' + PORT_OF_NEW_YORK;
202 | shipmentInPortEvent.message = message;
203 | emit(shipmentInPortEvent);
204 | }
205 |
206 | return getAssetRegistry(NS + '.Shipment')
207 | .then(function (shipmentRegistry) {
208 | // add the temp reading to the shipment
209 | return shipmentRegistry.update(shipment);
210 | });
211 | }
212 |
213 | /**
214 | * Initialize some test assets and participants useful for running a demo.
215 | * @param {org.acme.shipping.perishable.SetupDemo} setupDemo - the SetupDemo transaction
216 | * @transaction
217 | */
218 | function setupDemo(setupDemo) {
219 |
220 | var factory = getFactory();
221 | var NS = 'org.acme.shipping.perishable';
222 |
223 | // create the grower
224 | var grower = factory.newResource(NS, 'Grower', 'farmer@email.com');
225 | var growerAddress = factory.newConcept(NS, 'Address');
226 | growerAddress.country = 'USA';
227 | grower.address = growerAddress;
228 | grower.accountBalance = 0;
229 |
230 | // create the importer
231 | var importer = factory.newResource(NS, 'Importer', 'supermarket@email.com');
232 | var importerAddress = factory.newConcept(NS, 'Address');
233 | importerAddress.country = 'UK';
234 | importer.address = importerAddress;
235 | importer.accountBalance = 0;
236 |
237 | // create the shipper
238 | var shipper = factory.newResource(NS, 'Shipper', 'shipper@email.com');
239 | var shipperAddress = factory.newConcept(NS, 'Address');
240 | shipperAddress.country = 'Panama';
241 | shipper.address = shipperAddress;
242 | shipper.accountBalance = 0;
243 |
244 | // create the contract
245 | var contract = factory.newResource(NS, 'Contract', 'CON_002');
246 | contract.grower = factory.newRelationship(NS, 'Grower', 'farmer@email.com');
247 | contract.importer = factory.newRelationship(NS, 'Importer', 'supermarket@email.com');
248 | contract.shipper = factory.newRelationship(NS, 'Shipper', 'shipper@email.com');
249 | var tomorrow = setupDemo.timestamp;
250 | tomorrow.setDate(tomorrow.getDate() + 1);
251 | contract.arrivalDateTime = tomorrow; // the shipment has to arrive tomorrow
252 | contract.unitPrice = 0.5; // pay 50 cents per unit
253 | contract.minTemperature = 2; // min temperature for the cargo
254 | contract.maxTemperature = 10; // max temperature for the cargo
255 | contract.maxAccel = 15000; // max acceleration for the cargo
256 | contract.minPenaltyFactor = 0.2; // we reduce the price by 20 cents for every degree below the min temp
257 | contract.maxPenaltyFactor = 0.1; // we reduce the price by 10 cents for every degree above the max temp
258 |
259 | // create the shipment
260 | var shipment = factory.newResource(NS, 'Shipment', '320022000251363131363432');
261 | shipment.type = 'MEDICINE';
262 | shipment.status = 'IN_TRANSIT';
263 | shipment.unitCount = 5000;
264 | shipment.contract = factory.newRelationship(NS, 'Contract', 'CON_002');
265 | return getParticipantRegistry(NS + '.Grower')
266 | .then(function (growerRegistry) {
267 | // add the growers
268 | return growerRegistry.addAll([grower]);
269 | })
270 | .then(function() {
271 | return getParticipantRegistry(NS + '.Importer');
272 | })
273 | .then(function(importerRegistry) {
274 | // add the importers
275 | return importerRegistry.addAll([importer]);
276 | })
277 | .then(function() {
278 | return getParticipantRegistry(NS + '.Shipper');
279 | })
280 | .then(function(shipperRegistry) {
281 | // add the shippers
282 | return shipperRegistry.addAll([shipper]);
283 | })
284 | .then(function() {
285 | return getAssetRegistry(NS + '.Contract');
286 | })
287 | .then(function(contractRegistry) {
288 | // add the contracts
289 | return contractRegistry.addAll([contract]);
290 | })
291 | .then(function() {
292 | return getAssetRegistry(NS + '.Shipment');
293 | })
294 | .then(function(shipmentRegistry) {
295 | // add the shipments
296 | return shipmentRegistry.addAll([shipment]);
297 | });
298 | }
299 |
--------------------------------------------------------------------------------
/Blockchain/IoT-Perishable-Network/models/perishable.cto:
--------------------------------------------------------------------------------
1 | /**
2 | * A business network for shipping perishable goods
3 | * The cargo is temperature controlled and contracts
4 | * can be negociated based on the temperature
5 | * readings received for the cargo
6 | */
7 |
8 | namespace org.acme.shipping.perishable
9 |
10 | /**
11 | * The type of perishable product being shipped
12 | */
13 | enum ProductType {
14 | o BANANAS
15 | o APPLES
16 | o PEARS
17 | o PEACHES
18 | o COFFEE
19 | o MEDICINE
20 | }
21 |
22 | /**
23 | * The status of a shipment
24 | */
25 | enum ShipmentStatus {
26 | o CREATED
27 | o IN_TRANSIT
28 | o ARRIVED
29 | }
30 |
31 | /**
32 | * Directions of the compass
33 | */
34 | enum CompassDirection {
35 |
36 | }
37 |
38 | /**
39 | * An abstract transaction that is related to a Shipment
40 | */
41 | abstract transaction ShipmentTransaction {
42 | --> Shipment shipment
43 | }
44 |
45 | /**
46 | * An Accelerometer reading for a shipment. E.g. received from a
47 | * device within an accelerometer controlled shipping container
48 | *
49 | * The combination of the accelerometer environment reading,
50 | * PLUS the GPS location, PLUS the timestamp is what is interesting
51 | * Just knowing temperature without knowing where or when is
52 | * not sufficient.
53 | */
54 | transaction AccelReading extends ShipmentTransaction {
55 |
56 | }
57 |
58 | /**
59 | * An temperature reading for a shipment. E.g. received from a
60 | * device within a temperature controlled shipping container
61 | *
62 | * The combination of the temperature environment reading,
63 | * PLUS the GPS location, PLUS the timestamp is what is interesting
64 | * Just knowing temperature without knowing where or when is
65 | * not sufficient.
66 | */
67 | transaction TemperatureReading extends ShipmentTransaction {
68 |
69 | }
70 |
71 | /**
72 | * A GPS reading for a shipment. E.g. received from a device
73 | * within a shipping container
74 | */
75 | transaction GpsReading extends ShipmentTransaction {
76 |
77 | }
78 |
79 | /**
80 | * A notification that a shipment has been received by the
81 | * importer and that funds should be transferred from the importer
82 | * to the grower to pay for the shipment.
83 | */
84 | transaction ShipmentReceived extends ShipmentTransaction {
85 |
86 | }
87 |
88 | /**
89 | * A shipment being tracked as an asset on the ledger
90 | */
91 | asset Shipment identified by shipmentId {
92 | o String shipmentId
93 | o ProductType type
94 | o ShipmentStatus status
95 | o Long unitCount
96 | --> Contract contract
97 |
98 | }
99 |
100 | /**
101 | * Defines a contract between a Grower and an Importer to ship using
102 | * a Shipper, paying a set unit price. The unit price is multiplied by
103 | * a penality factor proportional to the deviation from the min and max
104 | * negociated temperatures for the shipment.
105 | */
106 | asset Contract identified by contractId {
107 | o String contractId
108 | --> Grower grower
109 | --> Shipper shipper
110 | --> Importer importer
111 | o DateTime arrivalDateTime
112 | o Double unitPrice
113 | o Double minTemperature
114 | o Double maxTemperature
115 | o Double minPenaltyFactor
116 | o Double maxPenaltyFactor
117 | }
118 |
119 | /**
120 | * A concept for a simple street address
121 | */
122 | concept Address {
123 | o String city optional
124 | o String country
125 | o String street optional
126 | o String zip optional
127 | }
128 |
129 | /**
130 | * An abstract participant type in this business network
131 | */
132 | abstract participant Business identified by email {
133 | o String email
134 | o Address address
135 | o Double accountBalance
136 | }
137 |
138 | /**
139 | * A Grower is a type of participant in the network
140 | */
141 | participant Grower extends Business {
142 | }
143 |
144 | /**
145 | * A Shipper is a type of participant in the network
146 | */
147 | participant Shipper extends Business {
148 | }
149 |
150 | /**
151 | * An Importer is a type of participant in the network
152 | */
153 | participant Importer extends Business {
154 | }
155 |
156 | /**
157 | * JUST FOR INITIALIZING A DEMO
158 | */
159 | transaction SetupDemo {
160 | }
161 |
162 | /**
163 | * An event - when the temperature goes outside the agreed-upon boundaries
164 | */
165 | event TemperatureThresholdEvent {
166 |
167 | }
168 |
169 | /**
170 | * An event - when the acceleration event has been detected
171 | */
172 | event AccelerationThresholdEvent {
173 |
174 | }
175 |
176 | /**
177 | * An event - when the ship arrives at the port
178 | */
179 | event ShipmentInPortEvent {
180 |
181 | }
--------------------------------------------------------------------------------
/Blockchain/IoT-Perishable-Network/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "engines": {
3 | "composer": "^0.15.0"
4 | },
5 | "name": "iot-asset-tracker-network",
6 | "version": "0.1.0",
7 | "description": "IoT Asset Tracker Perishable Goods Business Network",
8 | "scripts": {
9 | "clean": "rm -Rf ./node_modules ./dist ./composer-logs ./out",
10 | "prepublish": "mkdirp ./dist && composer archive create --sourceType dir --sourceName . -a ./dist/iot-asset-tracker-network.bna",
11 | "pretest": "npm run lint",
12 | "lint": "eslint .",
13 | "postlint": "npm run licchk",
14 | "licchk": "license-check",
15 | "postlicchk": "npm run doc",
16 | "doc": "jsdoc --pedantic --recurse -c jsdoc.json",
17 | "test": "mocha -t 0 --recursive && cucumber-js",
18 | "deploy": "./scripts/deploy.sh"
19 | },
20 | "repository": {
21 | "type": "git",
22 | "url": "https://github.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain.git"
23 | },
24 | "keywords": [
25 | "shipping",
26 | "goods",
27 | "perishable",
28 | "asset-tracking",
29 | "asset-tracker",
30 | "composer",
31 | "composer-network",
32 | "iot"
33 | ],
34 | "author": "Hyperledger Composer",
35 | "license": "Apache-2.0",
36 | "devDependencies": {
37 | "browserfs": "^1.2.0",
38 | "chai": "latest",
39 | "chai-as-promised": "latest",
40 | "composer-admin": "^0.19.1",
41 | "composer-cli": "^0.19.1",
42 | "composer-client": "^0.19.1",
43 | "composer-common": "^0.19.1",
44 | "composer-connector-embedded": "^0.19.1",
45 | "composer-cucumber-steps": "^0.19.1",
46 | "cucumber": "^2.2.0",
47 | "eslint": "latest",
48 | "istanbul": "^0.4.5",
49 | "jsdoc": "^3.5.5",
50 | "license-check": "^1.1.5",
51 | "mkdirp": "latest",
52 | "mocha": "latest",
53 | "moment": "^2.17.1",
54 | "nyc": "latest"
55 | },
56 | "license-check-config": {
57 | "src": [
58 | "**/*.js",
59 | "!./coverage/**/*",
60 | "!./node_modules/**/*",
61 | "!./out/**/*",
62 | "!./scripts/**/*"
63 | ],
64 | "path": "header.txt",
65 | "blocking": true,
66 | "logInfo": false,
67 | "logError": true
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/Blockchain/IoT-Perishable-Network/perishable.cto:
--------------------------------------------------------------------------------
1 | /**
2 | * A business network for shipping perishable goods
3 | * The cargo is temperature controlled and contracts
4 | * can be negociated based on the temperature
5 | * readings received for the cargo
6 | */
7 |
8 | namespace org.acme.shipping.perishable
9 |
10 | /**
11 | * The type of perishable product being shipped
12 | */
13 | enum ProductType {
14 | o BANANAS
15 | o APPLES
16 | o PEARS
17 | o PEACHES
18 | o COFFEE
19 | o MEDICINE
20 | }
21 |
22 | /**
23 | * The status of a shipment
24 | */
25 | enum ShipmentStatus {
26 | o CREATED
27 | o IN_TRANSIT
28 | o ARRIVED
29 | }
30 |
31 | /**
32 | * Directions of the compass
33 | */
34 | enum CompassDirection {
35 | o N
36 | o S
37 | o E
38 | o W
39 | }
40 |
41 | /**
42 | * An abstract transaction that is related to a Shipment
43 | */
44 | abstract transaction ShipmentTransaction {
45 | --> Shipment shipment
46 | }
47 |
48 | /**
49 | * An Accelerometer reading for a shipment. E.g. received from a
50 | * device within an accelerometer controlled shipping container
51 | *
52 | * The combination of the accelerometer environment reading,
53 | * PLUS the GPS location, PLUS the timestamp is what is interesting
54 | * Just knowing temperature without knowing where or when is
55 | * not sufficient.
56 | */
57 | transaction AccelReading extends ShipmentTransaction {
58 | o Double accel_x
59 | o Double accel_y
60 | o Double accel_z
61 | o String latitude
62 | o String longitude
63 | o String readingTime
64 | }
65 |
66 | /**
67 | * An temperature reading for a shipment. E.g. received from a
68 | * device within a temperature controlled shipping container
69 | *
70 | * The combination of the temperature environment reading,
71 | * PLUS the GPS location, PLUS the timestamp is what is interesting
72 | * Just knowing temperature without knowing where or when is
73 | * not sufficient.
74 | */
75 | transaction TemperatureReading extends ShipmentTransaction {
76 | o Double celsius
77 | o String latitude
78 | o String longitude
79 | o String readingTime
80 | }
81 |
82 | /**
83 | * A GPS reading for a shipment. E.g. received from a device
84 | * within a shipping container
85 | */
86 | transaction GpsReading extends ShipmentTransaction {
87 | o String readingTime
88 | o String readingDate
89 | o String latitude
90 | o CompassDirection latitudeDir
91 | o String longitude
92 | o CompassDirection longitudeDir
93 | }
94 |
95 | /**
96 | * A notification that a shipment has been received by the
97 | * importer and that funds should be transferred from the importer
98 | * to the grower to pay for the shipment.
99 | */
100 | transaction ShipmentReceived extends ShipmentTransaction {
101 | }
102 |
103 | /**
104 | * A shipment being tracked as an asset on the ledger
105 | */
106 | asset Shipment identified by shipmentId {
107 | o String shipmentId
108 | o ProductType type
109 | o ShipmentStatus status
110 | o Long unitCount
111 | --> Contract contract
112 | o TemperatureReading[] temperatureReadings optional
113 | o AccelReading[] AccelReadings optional
114 | o GpsReading[] gpsReadings optional
115 | }
116 |
117 | /**
118 | * Defines a contract between a Grower and an Importer to ship using
119 | * a Shipper, paying a set unit price. The unit price is multiplied by
120 | * a penality factor proportional to the deviation from the min and max
121 | * negociated temperatures for the shipment.
122 | */
123 | asset Contract identified by contractId {
124 | o String contractId
125 | --> Grower grower
126 | --> Shipper shipper
127 | --> Importer importer
128 | o DateTime arrivalDateTime
129 | o Double unitPrice
130 | o Double minTemperature
131 | o Double maxTemperature
132 | o Double minPenaltyFactor
133 | o Double maxPenaltyFactor
134 | o Double maxAccel
135 | }
136 |
137 | /**
138 | * A concept for a simple street address
139 | */
140 | concept Address {
141 | o String city optional
142 | o String country
143 | o String street optional
144 | o String zip optional
145 | }
146 |
147 | /**
148 | * An abstract participant type in this business network
149 | */
150 | abstract participant Business identified by email {
151 | o String email
152 | o Address address
153 | o Double accountBalance
154 | }
155 |
156 | /**
157 | * A Grower is a type of participant in the network
158 | */
159 | participant Grower extends Business {
160 | }
161 |
162 | /**
163 | * A Shipper is a type of participant in the network
164 | */
165 | participant Shipper extends Business {
166 | }
167 |
168 | /**
169 | * An Importer is a type of participant in the network
170 | */
171 | participant Importer extends Business {
172 | }
173 |
174 | /**
175 | * JUST FOR INITIALIZING A DEMO
176 | */
177 | transaction SetupDemo {
178 | }
179 |
180 | /**
181 | * An event - when the temperature goes outside the agreed-upon boundaries
182 | */
183 | event TemperatureThresholdEvent {
184 | o String message
185 | o Double temperature
186 | o String latitude
187 | o String longitude
188 | o String readingTime
189 | --> Shipment shipment
190 | }
191 |
192 | /**
193 | * An event - when the acceleration event has been detected
194 | */
195 | event AccelerationThresholdEvent {
196 | o String message
197 | o Double accel_x
198 | o Double accel_y
199 | o Double accel_z
200 | o String latitude
201 | o String longitude
202 | o String readingTime
203 | --> Shipment shipment
204 | }
205 |
206 | /**
207 | * An event - when the ship arrives at the port
208 | */
209 | event ShipmentInPortEvent {
210 | o String message
211 | --> Shipment shipment
212 | }
213 |
--------------------------------------------------------------------------------
/Blockchain/IoT-Perishable-Network/permissions.acl:
--------------------------------------------------------------------------------
1 | /**
2 | * Sample access control list.
3 | */
4 | rule Default {
5 | description: "Allow all participants access to all resources"
6 | participant: "ANY"
7 | operation: ALL
8 | resource: "org.acme.shipping.perishable.*"
9 | action: ALLOW
10 | }
11 |
12 | rule SystemACL {
13 | description: "System ACL to permit all access"
14 | participant: "org.hyperledger.composer.system.Participant"
15 | operation: ALL
16 | resource: "org.hyperledger.composer.system.**"
17 | action: ALLOW
18 | }
19 |
20 | rule NetworkAdminUser {
21 | description: "Grant business network administrators full access to user resources"
22 | participant: "org.hyperledger.composer.system.NetworkAdmin"
23 | operation: ALL
24 | resource: "**"
25 | action: ALLOW
26 | }
27 |
28 | rule NetworkAdminSystem {
29 | description: "Grant business network administrators full access to system resources"
30 | participant: "org.hyperledger.composer.system.NetworkAdmin"
31 | operation: ALL
32 | resource: "org.hyperledger.composer.system.**"
33 | action: ALLOW
34 | }
--------------------------------------------------------------------------------
/Blockchain/README-ja.md:
--------------------------------------------------------------------------------
1 | *Read this in other languages: [English](README.md).*
2 |
3 | # Hyperledger ブロックチェーン上の IoT 資産トラッカー
4 |
5 | IoT 資産追跡ワークショップのこのセクションは、実際には2つの部分に分かれています。
6 | 最初の部分は **ブロックチェーン Aパート** と呼ばれ、IBM Cloud 上の [IBM Blockchain Starter Plan](https://www.ibm.com/blockchain/getting-started.html) に [Hyperledger](https://www.hyperledger.org/) Fabric と Hyperledger Composer をデプロイするチュートリアルに従います。
7 |
8 | 優れた IBM Blockchain チュートリアルが幾つか存在しますが、ここではこれを繰り返すつもりはありません。
9 | 私たちは道に沿って、それらを組み合わせて使用します。
10 | **ブロックチェーン Aパート** では、生鮮品のブロックチェーンビジネスネットワークを構築します。
11 |
12 | **ブロックチェーン Bパート** では、それを IBM Blockchain Starter プランにデプロイするためにスマートコントラクトに変換します。
13 | DevOps という IBM Cloud の一部を使用して、コードを作成し、IBM Blockchain Starter プランのインスタンスにデプロイします。
14 | 構築プロセスでは、Cloudly Foundry サービスとして動作する Hyperledger Composer Rest Server も IBM Cloud に導入します。
15 | Hyperledger Composer REST API は、Node-RED によってブロックチェーンの生鮮品のネットワークと通信するために使用されます。
16 | 最後に、Node-RED を操作して対話し、資産のトラッキングを視覚的に表示します。
17 |
18 | ## ブロックチェーン Aパート: 生鮮品ネットワークを構築
19 |
20 | 私たちは生鮮品ネットワークを構築するために Hyperledger Composer Playground を使用します。
21 | 作業が完了したら、Bパートで使用するコードをローカルシステムにエクスポートします。
22 |
23 | ### 生鮮品ネットワークのサンプルを Hyperledger Composer Playground にインポート
24 |
25 | 1. [IBM Hyperledger Composer Playground](https://blockchaindevelop.mybluemix.net/test) にアクセスします。
26 | 2. `Deploy a new business network` をクリックします。
27 | 
28 | 3. 下にスクロールして、npm のサンプルから `perishable-network` を選択します。
29 | 
30 | 4. 上にスクロールすると、ビジネスネットワークの名前は `perishable-network` になります。
31 | 5. `Give the network admin card` に名前 **admin@perishable-network** を指定します。
32 | 
33 | 6. 右側のサイドバーで、**Deploy** をクリックします。
34 | 7. **Connect now ->** をクリックします。
35 |
36 | 
37 |
38 | ### IoT トラッキングのための生鮮品ネットワークをカスタマイズする
39 |
40 | 導入した生鮮品ネットワークを見直してみましょう。
41 | これは温度を追跡しますが、地理情報は追跡しません。
42 | developerWorksには、生鮮品ネットワークを紹介する優れた3つの Hyperledger シリーズの記事があります。
43 |
44 | * [Hyperledger Composer basics, Part 1 - Model and test your blockchain network](https://www.ibm.com/developerworks/cloud/library/cl-refine-deploy-your-blockchain-network-with-hyperledger-composer-playground/index.html)
45 | * [Hyperledger Composer basics, Part 2 - Refine and deploy your blockchain network](https://www.ibm.com/developerworks/cloud/library/cl-refine-deploy-your-blockchain-network-with-hyperledger-composer-playground/index.html)
46 | * [Hyperledger Composer basics, Part 3 - Deploy locally, interact with, and extend your blockchain network](https://www.ibm.com/developerworks/cloud/library/cl-deploy-interact-extend-local-blockchain-network-with-hyperledger-composer/index.html)
47 |
48 | Part 2 記事は手順を含んでいます
49 |
50 | > 次に、パート1で作業した生鮮品ネットワークのサンプルを変更します。具体的には、船積みアセットに GPS 読み取り値を追加して IoT GPS センサーを出荷コンテナにモデル化し、スマートコントラクト (チェーンコード) が発送先ポートに到着したときにアラートを送信します。
51 |
52 | ええ、これはまさに **私たちがしたいこと** です。
53 | 素晴らしい!
54 | Steve Perry の [perishable-network git repository](
55 | https://github.com/makotogo/developerWorks) には、彼が dW の記事で詳しく述べた内容のバリエーションを含んでいます。
56 |
57 | もちろん、これら紹介したサンプルは私にとって完全なものではありません。
58 | なぜなら、Particle Electron 資産トラッカーから加速度計データもクラウドに送信したいからです。
59 |
60 | Hyperledger Blockchain モデリング言語の CTO ファイルとチェーンコードについて少し学ぶ必要があります。
61 | dW シリーズのパート1(上のリンク)は良い教材です。
62 |
63 | 次のステップでは、モデルファイルを変更して、加速度計データ、環境データ、地理位置データ、タイムスタンプを追加します。
64 | IoT データに追加するには、追加のトランザクションも必要です。
65 | モデルファイル更新後の時間を節約したい場合は、クローンしたリポジトリからトランザクションをインポートしてください。
66 |
67 | 1. モデルファイルで、**enum CompassDirection** を見つけるまでスクロールします。 次の値を入力して、4つの基本的な方向 (東西南北) を列挙します。
68 | ```
69 | /**
70 | * Directions of the compass
71 | */
72 | enum CompassDirection {
73 | o N
74 | o S
75 | o E
76 | o W
77 | }
78 | ```
79 | 2. 現在、センサーからデータを取得するためには、いくつかのトランザクションモデルが必要です。 空の **ShipmentTransaction を継承 (拡張) した AccelReading トランザクション** を完成するため、次の情報を入力します:
80 | ```
81 | transaction AccelReading extends ShipmentTransaction {
82 | o Double accel_x
83 | o Double accel_y
84 | o Double accel_z
85 | o String latitude
86 | o String longitude
87 | o String readingTime
88 | }
89 | ```
90 | 3. **ShipmentTransaction を継承した TemperatureReading トランザクション** に対しては、以下の変数に一致するように変更します:
91 | ```
92 | transaction TemperatureReading extends ShipmentTransaction {
93 | o Double celsius
94 | o String latitude
95 | o String longitude
96 | o String readingTime
97 | }
98 | ```
99 | 4. **ShipmentTransaction を継承した GpsReading トランザクション** を設定するときです:
100 | ```
101 | transaction GpsReading extends ShipmentTransaction {
102 | o String readingTime
103 | o String readingDate
104 | o String latitude
105 | o CompassDirection latitudeDir
106 | o String longitude
107 | o CompassDirection longitudeDir
108 | }
109 | ```
110 |
111 | 5. IoTデータを資産、出荷に関連付けるには、IoT関連の変数を出荷するための資産モデルに追加する必要があります。出荷モデルに以下の追加を行います。
112 | * AccelReading[] AccelReadings optional
113 | * GpsReading[] gpsReadings optional
114 |
115 | ```
116 | asset Shipment identified by shipmentId {
117 | o String shipmentId
118 | o ProductType type
119 | o ShipmentStatus status
120 | o Long unitCount
121 | --> Contract contract
122 | o TemperatureReading[] temperatureReadings optional
123 | o AccelReading[] AccelReadings optional
124 | o GpsReading[] gpsReadings optional
125 | }
126 | ```
127 |
128 | 6. 我々の契約は、現在、加速度計によって捕捉された事故なしに到着する出荷を前提としたものです。
129 | 加速度計値のフィールドを契約 (Contract) 資産モデルに追加する必要があります。
130 | これにより、logic.js ファイルの加速度計データに基づいて、衝突、ひどい揺れ、その他のインシデントの条件を指定することができます。
131 | * Contract 資産モデルに **Double maxAccel** を追加する。
132 |
133 | ```
134 | asset Contract identified by contractId {
135 | o String contractId
136 | --> Grower grower
137 | --> Shipper shipper
138 | --> Importer importer
139 | o DateTime arrivalDateTime
140 | o Double unitPrice
141 | o Double minTemperature
142 | o Double maxTemperature
143 | o Double minPenaltyFactor
144 | o Double maxPenaltyFactor
145 | o Double maxAccel
146 | }
147 | ```
148 | 7. ここで、いくつかのイベントを作成して、合意されたしきい値を超えた場合に、適切な参加者に警告する必要があります。下にスクロールして、**TemperatureThresholdEvent** に次の情報を入力します。
149 | ```
150 | event TemperatureThresholdEvent {
151 | o String message
152 | o Double temperature
153 | o String latitude
154 | o String longitude
155 | o String readingTime
156 | --> Shipment shipment
157 | }
158 | ```
159 |
160 | 8. **AccelerationThresholdEvent** に変数を作成します:
161 | ```
162 | event AccelerationThresholdEvent {
163 | o String message
164 | o Double accel_x
165 | o Double accel_y
166 | o Double accel_z
167 | o String latitude
168 | o String longitude
169 | o String readingTime
170 | --> Shipment shipment
171 | }
172 | ```
173 | 9. **ShipmentInPort** イベントのモデルを作成するための情報を記入します:
174 | ```
175 | event ShipmentInPortEvent {
176 | o String message
177 | --> Shipment shipment
178 | }
179 | ```
180 |
181 | 10. モデルファイルが完成しました。`Update` をクリックすると、Hyperledger Composer Playground に変更が保存されます。
182 | 
183 |
184 | 11. 私たちの新しい logic.js ファイルの内容を私たちの [リポジトリ](IoT-Perishable-Network/lib/logic.js) から **コピー** (CTRL+C) します。
185 |
186 | 12. Hyperledger Composer Playground に戻り:
187 | * logic.js ファイルの内容を **全て選択** (CTRL+A) して削除します
188 | * さきほどリポジトリの logic.js ファイルからコピーした内容を **ペースト** (CTRL+V) します
189 | * `Update` をクリックして変更を保存します
190 |
191 | 
192 |
193 | 13. さあ、私たちの仕事をテストしましょう!ページの上部にある `Test` タブをクリックします。
194 | 
195 |
196 | 14. まず、`Submit Transaction` を選択することで、*setupDemo* トランザクションを実行してデフォルト値を与えることができます。
197 |
198 | 
199 |
200 | 15. ドロップダウンから `SetupDemo` を選択して `Submit` します。
201 | 
202 |
203 | 16. あなたの3つの参加者と2つの資産を見てください。栽培業者(Grower)、輸入業者(Importer)、荷送人(Shipper)、貨物(Shipment)および契約(Contract)が定義されているはずです。
204 |
205 | 17. 他の取引と一緒に実行して、資産を更新するようにします。以下の例のように、貨物に追加された項目が詳細に表示されます。任意のデータを入力できます。架空のものでかまいません。
206 | 
207 |
208 | 18. デプロイメントの実行中に使用するため、コードをローカルシステムに `Export` します。
209 | 
210 |
211 | 19. ビジネスネットワークアーカイブ、**perishable-network.bna** ファイルをどこか簡単に見つけられる場所に保存します。
212 | 
213 |
214 | ## ブロックチェーン Bパート: 生鮮品ネットワークの実装
215 |
216 | さあ楽しい時間が始まります!これを2つのセクションに分けて説明します:
217 |
218 | * [ブロックチェーン・ネットワークを IBM Blockchain Starter プランにデプロイする](#deploy-your-network)
219 | * [Hyperledger Composer Rest Server を使用して、デプロイしたブロックチェーン・ネットワーク用の API を生成する](#working-with-the-rest-api)
220 |
221 |
222 | ### 自身のネットワークをデプロイする
223 |
224 | 自身のブロックチェーン・アプリケーションを作成したので、今度は IBM Blockchain Starter プランで実行させましょう。
225 | そのために、IBM Cloud の DevOps サービスを使用してコードをデプロイし、REST サーバーを開始します。
226 | 別の機会に同様のことをする場合、この全プロセスは [こちら](https://github.com/sstone1/blockchain-starter-kit/blob/master/README.md) に文書化されていますので参照してください。
227 | このプロセスにより、IBM Blockchain Starter プランが作成されます。
228 |
229 | **ノート:** IBM Blockchain Starter プランを使用するには、IBM Cloud アカウントを pay-as-you-go アカウントにアップグレードする必要があります。最大30日間無料です。料金の請求を避けるために使用量を監視するのを忘れないでください。
230 |
231 | これは以下の手順に分かれています:
232 | * [DevOps ツールチェーンを作成する](#create-a-devops-toolchain)
233 | * [Hyperledger Composer をローカル環境にインストールする](#install-hyperledger-composer-locally)
234 | * [デプロイのためのコードを準備する](#prepare-your-code-for-deployment)
235 | * [デプロイメントの検証](#verify-deployment)
236 |
237 |
238 | #### DevOps ツールチェーンを作成する
239 | 1. [こちら](https://console.bluemix.net/devops/setup/deploy/?repository=https%3A//github.com/sstone1/blockchain-starter-kit&branch=master&env_id=ibm%3Ayp%3Aus-south) で DevOps ツールチェーン作成を開始する。
240 |
241 | 2. あなたのツールチェーンの名前を入力してください。ユニークなものにしましょう!
242 |
243 | **ノート:** 以前に IBM Cloud で GitHub 認証を実施していない場合は、Blockchain Starter Kit を作成する前に実施する必要があります。この画面をスクロールして認証ボタンを選択してください。
244 |
245 | 
246 |
247 | 3. 下にスクロールしてユニークなリポジトリ名 **XXX-blockchain-toolkit** を作成します。XXXはあなたの頭文字です。
248 |
249 | 4. `Create` をクリック。
250 | 
251 |
252 | 5. おめでとうございます!コードをデプロイするために使用できる完全なツールチェーンが用意されました。
253 | 
254 |
255 | 途中の `GitHub` ボタンを押すと、新しく作成した GitHub リポジトリに移動します。この GitHub リポジトリをローカル開発環境にクローンすることで、ブロックチェーンアプリケーションを操作できます。
256 |
257 | 右側の `Delivery Pipeline` ボタンをクリックすると、DevOps ツールチェーンのデリバリーパイプラインに移動します。ここからは、ブロックチェーンアプリケーションの最新の自動ビルドとデプロイメントの結果を調べることができます。
258 |
259 |
260 | #### Hyperledger Composer をローカル環境にインストールする
261 | コードを展開するには、システム上の Hyperledger Composer コマンドのいくつかを使用する必要があります。
262 |
263 | 1. 前提条件のインストールと Hyperledger Composerの インストールについては、[指示](https://hyperledger.github.io/composer/latest/installing/installing-index) に従ってください。
264 | * この演習で Hyperledger Composer をインストールする場合は、手順1と手順2のみを完了してください。
265 |
266 |
267 | #### デプロイのためのコードを準備する
268 |
269 | 1. あなたのツールチェインで、`GitHub` アイコンを選択して、新しく作成したリポジトリを開きます。
270 | 
271 |
272 | 2. GitHubで、`Clone or download` をクリックし、`copy` アイコンをクリックして、リポジトリをローカルシステムにクローンするためのURLを取得します。
273 | 
274 |
275 | 3. あなたのローカルシステム上の端末で、 `git clone ` と入力します。`` は前の手順でコピーした値です。
276 | ```
277 | $ git clone https://github.com/SweetJenn23/XXX-blockchain-starter-kit.git
278 | Cloning into 'XXX-blockchain-starter-kit'...
279 | remote: Counting objects: 40, done.
280 | remote: Compressing objects: 100% (35/35), done.
281 | remote: Total 40 (delta 2), reused 40 (delta 2), pack-reused 0
282 | Unpacking objects: 100% (40/40), done.
283 | ```
284 |
285 | 4. `cd XXX-blockchain-starter-kit/contracts` でcontract 契約ディレクトリに移動します。XXXはあなたの頭文字です。
286 |
287 | 5. 私たちはブロックチェーンネットワーク(.bna)からスマートコントラクトを作成する必要があります。これを行うには、Yeoman と呼ばれる Hyperledger Composer と共にインストールされたツールの1つを使用します。これにより、Hyperledger Fabricに 展開できるスマートスマートコントラクトの雛形 (スケルトン) が作成されます。私たちはこの雛形に私たちの仕事をコピーしなければなりません。
288 |
289 | 雛形を作成するには、ローカルシステムの端末に `yo` と入力し、**XXX-perishable-network** という名のビジネスネットワークを作成します。XXXはあなたの頭文字です。プロンプトで残りの情報を入力します。
290 |
291 | 
292 |
293 | 6. コードをスケルトンにコピーするには、ビジネスネットワークアーカイブを展開する必要があります。
294 | * ローカルシステムの端末で、**perishable-network.bna** を保存したディレクトリに移動します。
295 | * ファイルの拡張子を変更します: `mv perishable-network.bna perishable-network.zip`
296 | * ファイルを解凍します: `unzip perishable-network.zip`
297 | ```
298 | > unzip perishable-network.zip
299 | Archive: perishable-network.zip
300 | extracting: package.json
301 | extracting: README.md
302 | extracting: permissions.acl
303 | creating: models/
304 | extracting: models/perishable.cto
305 | creating: lib/
306 | extracting: lib/logic.js
307 | ```
308 | 7. */XXX-blockchain-starter-kit/contracts/xxx-perishable-network* に、抽出したファイルをコピーします。*xxx-perishable-network* ディレクトリにあるファイルを同じ名前のファイルで置き換えます。次のすべてのファイルに対してこれを行います:
309 | * `/xxx-blockchain-starter-kit/contracts/xxx-perisable-network/lib/org.acme.biznet.perishable.cto` を削除
310 | * `perishable-network/README.md` を `XXX-blockchain-starter-kit/contracts/xxx-perishable-network` にコピー
311 | * `perishable-network/permissions.acl` を `XXX-blockchain-starter-kit/contracts/xxx-perishable-network` にコピー
312 | * `perishable-network/models/perishable.cto` を `XXX-blockchain-starter-kit/contracts/xxx-perishable-network/models/` にコピー
313 | * `perishable-network/lib/logic.js` を `XXX-blockchain-starter-kit/contracts/xxx-perishable-network/lib/` にコピー
314 |
315 | 
316 |
317 | 8. リポジトリの中のファイル **~/XXX-blockchain-starter-kit/.bluemix/pipeline_BUILD.sh** を編集します。
318 |
319 | * **function test_composer_contract** を探す
320 |
321 | * function 定義のなかで `#npm test` の行のコメントを外して **npm test** とする:
322 | ```
323 | function test_composer_contract {
324 | CONTRACT=$1
325 | echo testing composer contract ${CONTRACT}
326 | pushd contracts/${CONTRACT}
327 | npm install
328 | #npm test
329 | rm -rf node_modules
330 | popd
331 | }
332 | ```
333 |
334 | 9. ツールチェインの GitHub のリポジトリにコードをコミットするには、端末で **XXX-blockchain-starter-kit** ディレクトリ内で次のコマンドを実行する必要があります:
335 | * `git add -A`
336 | * `git commit -m "Update files"`
337 | * `git push`
338 |
339 | 
340 |
341 |
342 |
343 | #### デプロイメントの検証
344 |
345 | GitHub にコードをコミットすると、DevOps ツールチェインが自動的に変更を取得します。ツールチェインはすぐに変更のデプロイを開始します。
346 |
347 | 1. DevOps ツールチェーンページに移動し、`Delivery Pipeline` ボタンをクリックします。以下のページが表示され、デリバリーパイプラインの現在の状態の概要がわかります:
348 | 
349 |
350 | 2. デリバリーパイプラインには "BUILD" と "DEPLOY" の2つのフェーズがあります。
351 |
352 | デリバリーパイプラインの **BUILD** フェーズは、GitHubリポジトリをクローンし、依存関係をインストールし、すべてのスマートコントラクトの自動化ユニットテストをすべて実行します。ユニットテストが失敗した場合、デリバリーパイプラインは失敗し、変更はデプロイ(DEPLOY)されません。
353 |
354 | デリバリーパイプラインの **DEPLOY** フェーズは、スマート・コントラクトを IBM Cloud にデプロイします。
355 | IBM Blockchain Platform: Starter プラン (ブロックチェーンネットワーク) のインスタンス、Cloudant (ブロックチェーン資格情報の保存場所)のインスタンス、スマートコントラクトのデプロイ、デプロイ各スマートコントラクト用の RESTful API サーバーのプロビジョニングと構成を担当します。
356 |
357 | `View logs and history` をクリックすると、ビルドの最新ログが表示されます:
358 | 
359 |
360 | BUILD と DELIVERY 両方のフェーズが緑色ならば、エラーが発生していないことを示します。そうでない場合は、ログを使用してエラーの原因を調査する必要があります。
361 |
362 |
363 | ### REST API を使用してビジネスネットワークを公開する
364 |
365 | Node-RED からブロックチェーンを操作するために、Hyperledger Composer REST API を使用して perishable-network ビジネスネットワークを公開します。現在、このスターターキットでは、Hyperledger Fabric を使用して開発されたスマートコントラクト用の RESTful API サーバーはデプロイされていません。Hyperledger Composer を使用しているので、DevOps ツールチェーンは、配備された各スマートコントラクトに対して RESTful AP Iサーバーを自動的にデプロイしました。これらの RESTful API を使用して、スマートコントラクトと対話するエンドユーザー・アプリケーションを構築できます。
366 |
367 | 1. デプロイされた RESTful API サーバーのURLは、"DELIVERY" フェーズのログで確認できますが、[IBM Cloud Dashboard](https://console.bluemix.net/dashboard/apps) でも見つけることができます。RESTful API サーバーは "composer-rest-server-" という名前とスマートコントラクトの名前で、アプリケーションとしてデプロイされます。 私たちは **composer-rest-server-xxx-perishable-network** という名前を使用します。
368 | 
369 |
370 | 2. rest サーバーをクリックして、アプリケーションの詳細ページに移動します。
371 | 
372 |
373 | 3. `Visit App URL` であなたの API を確認できます。
374 | 
375 |
376 | 4. これらのAPIは、Node-RED がブロックチェーンと通信する方法を提供しています。
377 | 
378 |
379 | おめでとう! あなたはワークショップの Blockchain セクションを完了しました。
380 | [Node-RED セクション](../Node-RED/README-ja.md) に進み、
381 | IoT 資産環境センサーのデータをトランザクション履歴に書き込み/読み取り/可視化できるようにした REST API を活用してください。
382 |
--------------------------------------------------------------------------------
/Blockchain/README.md:
--------------------------------------------------------------------------------
1 | *Read this in other languages: [日本語](README-ja.md).*
2 |
3 | # IoT Asset Tracking on a Hyperledger Blockchain
4 |
5 | This section of the IoT Asset tracking workshop is really split into two parts. The first part, which we will call **Blockchain Part A**, follows the tutorial to deploy a [Hyperledger](https://www.hyperledger.org/) Fabric and Hyperledger Composer running in the [IBM Blockchain Starter Plan](https://www.ibm.com/blockchain/getting-started.html) in the IBM Cloud.
6 |
7 | There are quite a few IBM Blockchain tutorials that are excellent and we won't try to repeat them here. We will be using a couple of them along the way. In **Blockchain Part A** we are going to create our blockchain business network of perishable goods. In **Blockchain Part B** we will convert it into smart contracts to deploy to the IBM Blockchain Starter Plan. We will use part of the IBM Cloud called DevOps to build our code and deploy it to an instance of the IBM Blockchain Starter Plan. The build process will also deploy a Hyperledger Composer Rest Server running as a Cloud Foundry service in the IBM Cloud. The Hyperledger Composer REST APIs will be used by Node-RED to talk to the blockchain perishable network. Finally, you'll get to work with Node-RED to interact and visually see the tracking of the asset.
8 |
9 | ## Blockchain Part A - Build your perishable network
10 |
11 | We will be using Hyperledger Composer Playground to build our perishable network. When we are done, we will export the code to our local system to use in Part B.
12 |
13 | ### Import the sample perishable network into Hyperledger Composer Playground
14 | 1. Access the [IBM Hyperledger Composer Playground](https://blockchaindevelop.mybluemix.net/test).
15 | 2. Click on **Deploy a new business network**
16 | 
17 | 3. Scroll down and choose **perishable-network** from the samples on npm.
18 | 
19 | 4. Scrolling back to the top, you should now have a business network name of **perishable-network**.
20 | 5. Give the network admin card that will be created a name **admin@perishable-network**.
21 | 
22 | 6. On the right sidebar, click on **Deploy**.
23 | 7. Press **Connect now ->**
24 |
25 | 
26 |
27 | ### Customize the perishable network for IoT tracking
28 | Let's pause for a moment to review the perishable-network you just deployed. It tracks temperature but not geolocation information. There is an excellent three part Hyperledger series of articles in developerWorks that introduce the perishable-network.
29 | * [Hyperledger Composer basics, Part 1 - Model and test your blockchain network](https://www.ibm.com/developerworks/cloud/library/cl-refine-deploy-your-blockchain-network-with-hyperledger-composer-playground/index.html)
30 | * [Hyperledger Composer basics, Part 2 - Refine and deploy your blockchain network](https://www.ibm.com/developerworks/cloud/library/cl-refine-deploy-your-blockchain-network-with-hyperledger-composer-playground/index.html)
31 | * [Hyperledger Composer basics, Part 3 - Deploy locally, interact with, and extend your blockchain network](https://www.ibm.com/developerworks/cloud/library/cl-deploy-interact-extend-local-blockchain-network-with-hyperledger-composer/index.html)
32 |
33 | Part 2 includes instructions
34 |
35 | > Then you'll make changes to the sample Perishable Goods network that you worked with in Part 1. Specifically, you'll model an IoT GPS sensor in the shipping container by adding GPS readings to the Shipment asset, and modify the smart contract (chaincode) to send an alert when the Shipment reaches its destination port.
36 |
37 | Well, duh. THAT'S WHAT WE WANT TO DO.... With full step by step instructions. Triple word score. Following all the links finds Steve Perry's [perishable-network git repository](
38 | https://github.com/makotogo/developerWorks) that contains the variants he details in the dW articles.
39 |
40 | Of course, those samples only got me so far because I also want to send accelerometer data from the Particle Electron Asset Tracker to the cloud.
41 |
42 | We're going to need to learn a little bit about the Hyperledger Blockchain modeling language CTO files and chaincode. Part 1 of the dW Series (link above) is a good primer.
43 |
44 | In the following steps, we will make changes to the model file to add in accelerometer data, environmental data, geolocation and a timestamp. Adding in the IoT data will also require additional transactions. To save time after we complete the model file updates, we will import the transactions from a cloned repository.
45 |
46 | 1. In your model file, scroll until you find **enum CompassDirection**. Enter the following values to enumerate the four cardinal directions:
47 | ```
48 | /**
49 | * Directions of the compass
50 | */
51 | enum CompassDirection {
52 | o N
53 | o S
54 | o E
55 | o W
56 | }
57 | ```
58 | 2. Now we need some transaction models to be able to get data from our sensors. In the empty **transaction AccelReading extends ShipmentTransaction** complete the following information:
59 | ```
60 | transaction AccelReading extends ShipmentTransaction {
61 | o Double accel_x
62 | o Double accel_y
63 | o Double accel_z
64 | o String latitude
65 | o String longitude
66 | o String readingTime
67 | }
68 | ```
69 | 3. For **transaction TemperatureReading extends ShipmentTransaction** modify the transaction to match the following variables:
70 | ```
71 | transaction TemperatureReading extends ShipmentTransaction {
72 | o Double celsius
73 | o String latitude
74 | o String longitude
75 | o String readingTime
76 | }
77 | ```
78 | 4. It's time to setup the **transaction GpsReading extends ShipmentTransaction**:
79 | ```
80 | transaction GpsReading extends ShipmentTransaction {
81 | o String readingTime
82 | o String readingDate
83 | o String latitude
84 | o CompassDirection latitudeDir
85 | o String longitude
86 | o CompassDirection longitudeDir
87 | }
88 | ```
89 |
90 | 5. For the IoT data to be associated with the asset, shipment, we will need to add some IoT related variables to the asset model for shipment. Make the following additions to the shipment model.
91 | * AccelReading[] AccelReadings optional
92 | * GpsReading[] gpsReadings optional
93 | ```
94 | asset Shipment identified by shipmentId {
95 | o String shipmentId
96 | o ProductType type
97 | o ShipmentStatus status
98 | o Long unitCount
99 | --> Contract contract
100 | o TemperatureReading[] temperatureReadings optional
101 | o AccelReading[] AccelReadings optional
102 | o GpsReading[] gpsReadings optional
103 | }
104 | ```
105 |
106 | 6. Our contract will also now be dependent on the shipment arriving without any incidents captured by the accelerometer. We will need to add a field for the accelerometer value to the contract asset model. This will allow us to specify conditions for a crash, a hard jolt or other incidents based on the accelerometer data in the logic.js file.
107 | * Add **Double maxAccel** to the Contract asset model.
108 | ```
109 | asset Contract identified by contractId {
110 | o String contractId
111 | --> Grower grower
112 | --> Shipper shipper
113 | --> Importer importer
114 | o DateTime arrivalDateTime
115 | o Double unitPrice
116 | o Double minTemperature
117 | o Double maxTemperature
118 | o Double minPenaltyFactor
119 | o Double maxPenaltyFactor
120 | o Double maxAccel
121 | }
122 | ```
123 | 7. Now we need to create some events so we can alert the appropriate participants when agreed upon thresholds are exceeded. Scroll down and fill in the following information for the **TemperatureThresholdEvent**.
124 | ```
125 | event TemperatureThresholdEvent {
126 | o String message
127 | o Double temperature
128 | o String latitude
129 | o String longitude
130 | o String readingTime
131 | --> Shipment shipment
132 | }
133 | ```
134 |
135 | 8. Create the variables for the **AccelerationThresholdEvent**.
136 | ```
137 | event AccelerationThresholdEvent {
138 | o String message
139 | o Double accel_x
140 | o Double accel_y
141 | o Double accel_z
142 | o String latitude
143 | o String longitude
144 | o String readingTime
145 | --> Shipment shipment
146 | }
147 | ```
148 | 9. Complete the information to create the model for the event **ShipmentInPort**.
149 | ```
150 | event ShipmentInPortEvent {
151 | o String message
152 | --> Shipment shipment
153 | }
154 | ```
155 |
156 | 10. Our model file is now complete. Select **Update** to save the changes in the Hyperledger Composer Playground.
157 | 
158 |
159 | 11. Now it is time to **copy** (CTRL+C) our new logic.js file from our [repository](IoT-Perishable-Network/lib/logic.js).
160 |
161 | 12. Back in the Hyperledger Composer Playground:
162 | * **Remove all of the content** (CTRL+A) in the logic.js file
163 | * **Paste** (CTRL+V) in the content copied from the logic.js file in our repository.
164 | * Select **Update** to save the changes.
165 | 
166 |
167 | 13. Now let's test our work! Click on the **Test** tab at the top of the page.
168 | 
169 |
170 | 14. First, select **Submit Transaction** so we can run our *setupDemo* transaction to give us some default values.
171 | 
172 |
173 | 15. From the *drop down*, select **SetupDemo** and then **Submit**.
174 | 
175 |
176 | 16. Look through your three partipants and two assets. You should now have a defined Grower, Importer, Shipper, Shipment and Contract.
177 |
178 | 17. Play with the other transactions to make sure that they update your assets. You should see fields added to your shipment in particular like the example below. You can enter any data. It doesn't need to be realistic.
179 | 
180 |
181 | 18. **Export** the code to your local system. We will use it during the deployment process.
182 | 
183 |
184 | 19. Save the business network archive, **perishable-network.bna**, somewhere you can easily find it.
185 | 
186 |
187 | ## Blockchain Part B - Implement a Perishable Business Network
188 | Now it's time for the fun to begin! We are going to break this down into two sections:
189 |
190 | * [Deploying your blockchain network to your IBM Blockchain Starter Plan](#deploy-your-network)
191 | * [Generating your API for your deployed blockchain network with Hyperledger Composer Rest Server](#working-with-the-rest-api)
192 |
193 |
194 | ### Deploy your network
195 | Now that you've created your blockchain application, it's time to make it run on the IBM Blockchain Starter Plan. To do that, we are going to use the DevOps service in the IBM Cloud to deploy our code and start a REST server. This entire process is documented [here](https://github.com/sstone1/blockchain-starter-kit/blob/master/README.md) if you are interested in doing something similar outside of this exercise. This process will create the IBM Blockchain Starter Plan for you.
196 |
197 | **NOTE:** You may have to upgrade your IBM Cloud account to a pay-as-you-go account to use the IBM Blockchain Starter Plan. It is free for up to 30 days. It is your responsibility to monitor usage to avoid fees.
198 |
199 | This breaks down into the following steps:
200 | * [Create a DevOps toolchain](#create-a-devops-toolchain)
201 | * [Installing Hyperledger Composer locally](#install-hyperledger-composer-locally)
202 | * [Moving your code into your repository](#prepare-your-code-for-deployment)
203 | * [Verifying deployment of code](#verify-deployment)
204 |
205 | #### Create a DevOps toolchain
206 | 1. Start [here](https://console.bluemix.net/devops/setup/deploy/?repository=https%3A//github.com/sstone1/blockchain-starter-kit&branch=master&env_id=ibm%3Ayp%3Aus-south) to create your DevOps toolchain.
207 |
208 | 2. Enter a name for your toolchain. Make it unique!
209 |
210 | **Note:** If you haven't authenticated with GitHub in IBM Cloud before, you will need to do this before you will be able to create the Blockchain Starter Kit. You can do this now by scrolling down on this screen and selecting the authenticate button.
211 |
212 | 
213 |
214 | 3. Scroll down and create a unique repository name, **XXX-blockchain-toolkit** where XXX are your initials.
215 |
216 | 4. Click **Create**.
217 | 
218 |
219 | 5. Congratulations! You have a complete toolchain that can be used to deploy your code.
220 | 
221 |
222 | The "GitHub" button in the middle will take you to your newly created GitHub repository. You will clone this GitHub repository into your local development environment, so you can work on your blockchain application.
223 |
224 | The "Delivery Pipeline" button on the right will take you to the delivery pipeline for your DevOps toolchain. From here, you can inspect the output from the latest automated build and deployment of your blockchain application.
225 |
226 | #### Install Hyperledger Composer locally
227 | To deploy our code, we'll need to work with some of the Hyperledger Composer commands on our system.
228 |
229 | 1. Follow the [directions](https://hyperledger.github.io/composer/latest/installing/installing-index) for installing the prerequisites and installing Hyperledger Composer.
230 | * Only complete Step 1 and Step 2 of installing Hyperledger Composer for this exercise.
231 |
232 | #### Prepare your code for deployment
233 | 1. In your toolchain, select the **GitHub** icon to open your newly created repository.
234 | 
235 |
236 | 2. In GitHub, click **Clone or download** and then the **copy** button to get the URL to use to clone your repository to your local system.
237 | 
238 |
239 | 3. In a terminal on your local system, enter `git clone ` where \ is the value you copied in the previous step.
240 | ```
241 | $ git clone https://github.com/SweetJenn23/XXX-blockchain-starter-kit.git
242 | Cloning into 'XXX-blockchain-starter-kit'...
243 | remote: Counting objects: 40, done.
244 | remote: Compressing objects: 100% (35/35), done.
245 | remote: Total 40 (delta 2), reused 40 (delta 2), pack-reused 0
246 | Unpacking objects: 100% (40/40), done.
247 | ```
248 |
249 | 4. Move into the contracts directory, `cd XXX-blockchain-starter-kit/contracts` where XXX are your initials.
250 |
251 | 5. We need to make a smart contract from our blockchain network (.bna). To do this we will use one of the tools installed with Hyperledger Composer called Yeoman. This will create a smart contract skeleton we can deploy to Hyperledger Fabric. We will have to copy our work into this skeleton.
252 |
253 | To make the skeleton, type `yo` into a terminal on your local system and create a business network named **XXX-perishable-network** where XXX are your initials. Complete the rest of the information in the prompts.
254 | 
255 |
256 | 6. To copy our code into the skeleton you'll need to expand the business network archive.
257 | * In your terminal, change directory to where your **perishable-network.bna** is saved.
258 | * Change the extension on the file. `mv perishable-network.bna perishable-network.zip`
259 | * Unzip the file. `unzip perishable-network.zip`
260 | ```
261 | > unzip perishable-network.zip
262 | Archive: perishable-network.zip
263 | extracting: package.json
264 | extracting: README.md
265 | extracting: permissions.acl
266 | creating: models/
267 | extracting: models/perishable.cto
268 | creating: lib/
269 | extracting: lib/logic.js
270 | ```
271 | 7. Copy the extracted files into your cloned GitHub directory, */XXX-blockchain-starter-kit/contracts/xxx-perishable-network*. Replace the files already in the *xxx-perishable-network* directory with the same name. Do this for all of the following files:
272 | * remove `/xxx-blockchain-starter-kit/contracts/xxx-perisable-network/lib/org.acme.biznet.perishable.cto`
273 | * copy `perishable-network/README.md` to `XXX-blockchain-starter-kit/contracts/xxx-perishable-network`
274 | * copy `perishable-network/permissions.acl` to `XXX-blockchain-starter-kit/contracts/xxx-perishable-network`
275 | * copy `perishable-network/models/perishable.cto` to `XXX-blockchain-starter-kit/contracts/xxx-perishable-network/models/`
276 | * copy `perishable-network/lib/logic.js` to `XXX-blockchain-starter-kit/contracts/xxx-perishable-network/lib/`
277 | 
278 |
279 | 8. In your repository edit the file, **~/XXX-blockchain-starter-kit/.bluemix/pipeline_BUILD.sh**
280 |
281 | * Find **function test_composer_contract**
282 |
283 | * In the function comment out the line **npm test**, `#npm test`
284 | ```
285 | function test_composer_contract {
286 | CONTRACT=$1
287 | echo testing composer contract ${CONTRACT}
288 | pushd contracts/${CONTRACT}
289 | npm install
290 | #npm test
291 | rm -rf node_modules
292 | popd
293 | }
294 | ```
295 |
296 | 9. To commit the code to your repository on GitHub for the toolchain you'll need to use the following in a terminal in your **XXX-blockchain-starter-kit** directory:
297 | * `git add -A`
298 | * `git commit -m "Update files"`
299 | * `git push`
300 | 
301 |
302 |
303 | #### Verify deployment
304 | When you committed your code to GitHub, the DevOps toolchain automatically picked up the changes. The toolchain will immediately begin deploying those changes.
305 |
306 | 1. Navigate to the DevOps toolchain page, and click on the "Delivery Pipeline" button. You should see the following page, giving you an overview of the current status of your delivery pipeline:
307 | 
308 |
309 | 2. The delivery pipeline is made up of two phases, "BUILD" and "DEPLOY".
310 |
311 | The "BUILD" phase of the delivery pipeline clones your GitHub repository, installs any dependencies, and runs all of the automated unit tests for all of your smart contracts. If any unit tests fail, then the delivery pipeline will fail and your changes will not be deployed.
312 |
313 | The "DEPLOY" phase of the delivery pipeline deploys your smart contracts into the IBM Cloud. It is reponsible for provisioning and configuring an instance of the IBM Blockchain Platform: Starter Plan (the blockchain network), an instance of Cloudant (the wallet for blockchain credentials), deploying the smart contracts, and deploying RESTful API servers for each deployed smart contract.
314 |
315 | If you click "View logs and history", you can see the latest logs for your build:
316 | 
317 |
318 | Both "BUILD" and "DELIVERY" phases should be green and showing that no errors have occurred. If this is not the case, you must use the logs to investigate the cause of the errors.
319 |
320 | ### Working with the REST API
321 |
322 | To manipulate the blockchain from Node-RED, we will expose the perishable-network business network using the Hyperledger Composer REST API. Currently, this starter kit does not deploy a RESTful API server for smart contracts developed using Hyperledger Fabric. Since we used Hyperledger Composer, the DevOps toolchain has automatically deployed a RESTful API server for each deployed smart contract. You can use these RESTful APIs to build end user applications that interact with a smart contract.
323 |
324 | 1. The URLs for the deployed RESTful API servers are available in the logs for the "DELIVERY" phase, but you can also find them in the [IBM Cloud Dashboard](https://console.bluemix.net/dashboard/apps). The RESTful API server is deployed as an application, with a name made up of "composer-rest-server-" and the name of the smart contract. Ours are called **composer-rest-server-xxx-perishable-network**.
325 | 
326 |
327 | 2. Click on the rest server to navigate to the application details page.
328 | 
329 |
330 | 3. Select the **Visit App URL** to view your API.
331 | 
332 |
333 | 4. These APIs are how Node-RED will communicate with blockchain.
334 | 
335 |
336 |
337 | Congratulations! You have completed the Blockchain section of the workshop. Proceed to the [Node-RED section](../Node-RED/README.md) which will leverage the REST API you just enabled to write / read / visualize IoT Asset environmental sensor data to the transaction history.
338 |
--------------------------------------------------------------------------------
/Blockchain/iot-asset-tracker-network.bna:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/iot-asset-tracker-network.bna
--------------------------------------------------------------------------------
/Blockchain/screenshots/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/.DS_Store
--------------------------------------------------------------------------------
/Blockchain/screenshots/API.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/API.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/Authorize.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/Authorize.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/AuthorizeCloud.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/AuthorizeCloud.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/Breadcrumbs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/Breadcrumbs.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/ConnectNow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/ConnectNow.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/Create.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/Create.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/DeliveryPipeline.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/DeliveryPipeline.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/DeployMarbles.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/DeployMarbles.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/DeploymentProgress.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/DeploymentProgress.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/DevOps.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/DevOps.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/Guided.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/Guided.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/MarblesToolchain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/MarblesToolchain.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/MarblesUI.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/MarblesUI.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/Passed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/Passed.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/Perishable-Network-BNA-ConnectNow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/Perishable-Network-BNA-ConnectNow.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/Perishable-Network-BNA-Model-update-annotated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/Perishable-Network-BNA-Model-update-annotated.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/Perishable-Network-BNA-annotated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/Perishable-Network-BNA-annotated.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/Perishable-Network-BNA-creds-annotated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/Perishable-Network-BNA-creds-annotated.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/Perishable-Network-REST-API-swagger.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/Perishable-Network-REST-API-swagger.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/RepoName.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/RepoName.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/SeeApp.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/SeeApp.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/SelectGitHub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/SelectGitHub.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/SetupDemo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/SetupDemo.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/SubmitTransaction.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/SubmitTransaction.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/Success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/Success.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/Test.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/Test.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/ToolChainName.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/ToolChainName.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/TrySamples.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/TrySamples.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/Update.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/Update.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/ViewLogs.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/ViewLogs.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/VisitAppURL.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/VisitAppURL.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/clonegithub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/clonegithub.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/completetoolchain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/completetoolchain.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/composer-rest-server.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/composer-rest-server.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/deploynew.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/deploynew.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/deploypassed.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/deploypassed.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/developcode.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/developcode.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/example.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/export.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/export.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/gitcommit.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/gitcommit.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/gotogithub.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/gotogithub.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/launchnow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/launchnow.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/menubar.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/menubar.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/movecontents.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/movecontents.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/npmsample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/npmsample.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/repositorycreate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/repositorycreate.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/restserverdetails.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/restserverdetails.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/savebna.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/savebna.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/starterkittoolchain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/starterkittoolchain.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/toolchainlog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/toolchainlog.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/webplayground.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/webplayground.png
--------------------------------------------------------------------------------
/Blockchain/screenshots/yo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Blockchain/screenshots/yo.png
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Apache License
2 | Version 2.0, January 2004
3 | http://www.apache.org/licenses/
4 |
5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6 |
7 | 1. Definitions.
8 |
9 | "License" shall mean the terms and conditions for use, reproduction,
10 | and distribution as defined by Sections 1 through 9 of this document.
11 |
12 | "Licensor" shall mean the copyright owner or entity authorized by
13 | the copyright owner that is granting the License.
14 |
15 | "Legal Entity" shall mean the union of the acting entity and all
16 | other entities that control, are controlled by, or are under common
17 | control with that entity. For the purposes of this definition,
18 | "control" means (i) the power, direct or indirect, to cause the
19 | direction or management of such entity, whether by contract or
20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
21 | outstanding shares, or (iii) beneficial ownership of such entity.
22 |
23 | "You" (or "Your") shall mean an individual or Legal Entity
24 | exercising permissions granted by this License.
25 |
26 | "Source" form shall mean the preferred form for making modifications,
27 | including but not limited to software source code, documentation
28 | source, and configuration files.
29 |
30 | "Object" form shall mean any form resulting from mechanical
31 | transformation or translation of a Source form, including but
32 | not limited to compiled object code, generated documentation,
33 | and conversions to other media types.
34 |
35 | "Work" shall mean the work of authorship, whether in Source or
36 | Object form, made available under the License, as indicated by a
37 | copyright notice that is included in or attached to the work
38 | (an example is provided in the Appendix below).
39 |
40 | "Derivative Works" shall mean any work, whether in Source or Object
41 | form, that is based on (or derived from) the Work and for which the
42 | editorial revisions, annotations, elaborations, or other modifications
43 | represent, as a whole, an original work of authorship. For the purposes
44 | of this License, Derivative Works shall not include works that remain
45 | separable from, or merely link (or bind by name) to the interfaces of,
46 | the Work and Derivative Works thereof.
47 |
48 | "Contribution" shall mean any work of authorship, including
49 | the original version of the Work and any modifications or additions
50 | to that Work or Derivative Works thereof, that is intentionally
51 | submitted to Licensor for inclusion in the Work by the copyright owner
52 | or by an individual or Legal Entity authorized to submit on behalf of
53 | the copyright owner. For the purposes of this definition, "submitted"
54 | means any form of electronic, verbal, or written communication sent
55 | to the Licensor or its representatives, including but not limited to
56 | communication on electronic mailing lists, source code control systems,
57 | and issue tracking systems that are managed by, or on behalf of, the
58 | Licensor for the purpose of discussing and improving the Work, but
59 | excluding communication that is conspicuously marked or otherwise
60 | designated in writing by the copyright owner as "Not a Contribution."
61 |
62 | "Contributor" shall mean Licensor and any individual or Legal Entity
63 | on behalf of whom a Contribution has been received by Licensor and
64 | subsequently incorporated within the Work.
65 |
66 | 2. Grant of Copyright License. Subject to the terms and conditions of
67 | this License, each Contributor hereby grants to You a perpetual,
68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69 | copyright license to reproduce, prepare Derivative Works of,
70 | publicly display, publicly perform, sublicense, and distribute the
71 | Work and such Derivative Works in Source or Object form.
72 |
73 | 3. Grant of Patent License. Subject to the terms and conditions of
74 | this License, each Contributor hereby grants to You a perpetual,
75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76 | (except as stated in this section) patent license to make, have made,
77 | use, offer to sell, sell, import, and otherwise transfer the Work,
78 | where such license applies only to those patent claims licensable
79 | by such Contributor that are necessarily infringed by their
80 | Contribution(s) alone or by combination of their Contribution(s)
81 | with the Work to which such Contribution(s) was submitted. If You
82 | institute patent litigation against any entity (including a
83 | cross-claim or counterclaim in a lawsuit) alleging that the Work
84 | or a Contribution incorporated within the Work constitutes direct
85 | or contributory patent infringement, then any patent licenses
86 | granted to You under this License for that Work shall terminate
87 | as of the date such litigation is filed.
88 |
89 | 4. Redistribution. You may reproduce and distribute copies of the
90 | Work or Derivative Works thereof in any medium, with or without
91 | modifications, and in Source or Object form, provided that You
92 | meet the following conditions:
93 |
94 | (a) You must give any other recipients of the Work or
95 | Derivative Works a copy of this License; and
96 |
97 | (b) You must cause any modified files to carry prominent notices
98 | stating that You changed the files; and
99 |
100 | (c) You must retain, in the Source form of any Derivative Works
101 | that You distribute, all copyright, patent, trademark, and
102 | attribution notices from the Source form of the Work,
103 | excluding those notices that do not pertain to any part of
104 | the Derivative Works; and
105 |
106 | (d) If the Work includes a "NOTICE" text file as part of its
107 | distribution, then any Derivative Works that You distribute must
108 | include a readable copy of the attribution notices contained
109 | within such NOTICE file, excluding those notices that do not
110 | pertain to any part of the Derivative Works, in at least one
111 | of the following places: within a NOTICE text file distributed
112 | as part of the Derivative Works; within the Source form or
113 | documentation, if provided along with the Derivative Works; or,
114 | within a display generated by the Derivative Works, if and
115 | wherever such third-party notices normally appear. The contents
116 | of the NOTICE file are for informational purposes only and
117 | do not modify the License. You may add Your own attribution
118 | notices within Derivative Works that You distribute, alongside
119 | or as an addendum to the NOTICE text from the Work, provided
120 | that such additional attribution notices cannot be construed
121 | as modifying the License.
122 |
123 | You may add Your own copyright statement to Your modifications and
124 | may provide additional or different license terms and conditions
125 | for use, reproduction, or distribution of Your modifications, or
126 | for any such Derivative Works as a whole, provided Your use,
127 | reproduction, and distribution of the Work otherwise complies with
128 | the conditions stated in this License.
129 |
130 | 5. Submission of Contributions. Unless You explicitly state otherwise,
131 | any Contribution intentionally submitted for inclusion in the Work
132 | by You to the Licensor shall be under the terms and conditions of
133 | this License, without any additional terms or conditions.
134 | Notwithstanding the above, nothing herein shall supersede or modify
135 | the terms of any separate license agreement you may have executed
136 | with Licensor regarding such Contributions.
137 |
138 | 6. Trademarks. This License does not grant permission to use the trade
139 | names, trademarks, service marks, or product names of the Licensor,
140 | except as required for reasonable and customary use in describing the
141 | origin of the Work and reproducing the content of the NOTICE file.
142 |
143 | 7. Disclaimer of Warranty. Unless required by applicable law or
144 | agreed to in writing, Licensor provides the Work (and each
145 | Contributor provides its Contributions) on an "AS IS" BASIS,
146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147 | implied, including, without limitation, any warranties or conditions
148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149 | PARTICULAR PURPOSE. You are solely responsible for determining the
150 | appropriateness of using or redistributing the Work and assume any
151 | risks associated with Your exercise of permissions under this License.
152 |
153 | 8. Limitation of Liability. In no event and under no legal theory,
154 | whether in tort (including negligence), contract, or otherwise,
155 | unless required by applicable law (such as deliberate and grossly
156 | negligent acts) or agreed to in writing, shall any Contributor be
157 | liable to You for damages, including any direct, indirect, special,
158 | incidental, or consequential damages of any character arising as a
159 | result of this License or out of the use or inability to use the
160 | Work (including but not limited to damages for loss of goodwill,
161 | work stoppage, computer failure or malfunction, or any and all
162 | other commercial damages or losses), even if such Contributor
163 | has been advised of the possibility of such damages.
164 |
165 | 9. Accepting Warranty or Additional Liability. While redistributing
166 | the Work or Derivative Works thereof, You may choose to offer,
167 | and charge a fee for, acceptance of support, warranty, indemnity,
168 | or other liability obligations and/or rights consistent with this
169 | License. However, in accepting such obligations, You may act only
170 | on Your own behalf and on Your sole responsibility, not on behalf
171 | of any other Contributor, and only if You agree to indemnify,
172 | defend, and hold each Contributor harmless for any liability
173 | incurred by, or claims asserted against, such Contributor by reason
174 | of your accepting any such warranty or additional liability.
175 |
176 | END OF TERMS AND CONDITIONS
177 |
178 | APPENDIX: How to apply the Apache License to your work.
179 |
180 | To apply the Apache License to your work, attach the following
181 | boilerplate notice, with the fields enclosed by brackets "{}"
182 | replaced with your own identifying information. (Don't include
183 | the brackets!) The text should be enclosed in the appropriate
184 | comment syntax for the file format. We also recommend that a
185 | file or class name and description of purpose be included on the
186 | same "printed page" as the copyright notice for easier
187 | identification within third-party archives.
188 |
189 | Copyright {yyyy} {name of copyright owner}
190 |
191 | Licensed under the Apache License, Version 2.0 (the "License");
192 | you may not use this file except in compliance with the License.
193 | You may obtain a copy of the License at
194 |
195 | http://www.apache.org/licenses/LICENSE-2.0
196 |
197 | Unless required by applicable law or agreed to in writing, software
198 | distributed under the License is distributed on an "AS IS" BASIS,
199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
200 | See the License for the specific language governing permissions and
201 | limitations under the License.
202 |
--------------------------------------------------------------------------------
/Node-RED/README-ja.md:
--------------------------------------------------------------------------------
1 | *Read this in other languages: [English](README.md).*
2 |
3 | # Node-RED - IoT 資産トラッカー
4 | ## Node-RED - IoT 資産トラッカー 前書き
5 |
6 | 
7 |
8 | 今回の Node-RED プログラムフローは、IoT資産トラッカーを実装し、Particle Electron からジオロケーションと環境センサーデータを受け取り、その情報を Hyperledger Fabric ブロックチェーンに格納し、マップ/ダッシュボード上の IoT デバイスのルートを視覚化します。
9 | 環境データが閾値を超えた場合に警告をトリガーします。
10 |
11 | このワークショップでは、GitHub からフローをコピーし、IBM Cloud 上で動作する Watson IoT / Node-RED Starter アプリケーションにデプロイします。
12 |
13 | 7つのフローは、次の機能を実行します:
14 |
15 | * **ブロックチェーンと Node-RED 変数を初期化** - すべてのフローを駆動するグローバル変数を設定します。
16 | * **Particle Electron の制御** - Particle Electron を有効/無効にする Node-RED Dashboard。
17 | * **Particle Electron イベントの受信** - Particle Electron イベントハンドラを購読する。
18 | * Hyperledger Fabric ブロックチェーンへの **Particle Electron データの書き込み**
19 | * **ブロックチェーンのトランザクション履歴をロード** し、IoTデバイスのルートをプロットする。
20 | * **Build a Dashboard を作成** し、デバイスの視覚化を制御する。
21 | * **記録された履歴に沿って IoT アセットを移動** することで、地図上にルートを視覚化する。
22 |
23 | ダッシュボードは、エンドユーザーにとって魅力的なユーザーエクスペリエンスではありません。これらのダッシュボードは、IoT 資産トラッカーで何か実装可能であるかを示すための、開発者向けのデモンストレーションです。エンドユーザーは、ジオロケーション座標には関心がないでしょう。
24 |
25 | ## IBM Cloud 上で Node-RED を使い始める
26 |
27 | IoT 資産トラッカーのダッシュボードを導入する前に、IBM Cloud 上で IoT Starter アプリケーションを作成する必要があります。このセクションでは、これらの手順について説明します。
28 |
29 | ### Internet of Things Starter アプリの作成
30 |
31 | * [IBM Cloud](http://bluemix.net) のアカウントを作成しログインする。
32 | * **(1)** のカタログをクリックし、 **(2)** 'internet of things' を検索する。
33 | * Internet of Things Platform Starter **(3)** ボイラープレートは、あらかじめ組み立てられたサービスが一緒に働くパターンです。 Internet of Things Platform Starter には、Node-RED Node.js Webサーバー、フローを格納する Cloudant データベース、IoT プラットフォームサービスが含まれているため、デバイスを接続できます。
34 | 
35 | * アプリケーションに何かユニークな名前を決めましょう。もし *myapp* という名前をつけたのなら、あなたのアプリケーションは http://myapp.mybluemix.net のURLアドレスに配置されるでしょう。*myapp* アプリケーションとそのURLは、IBM Cloud 内で1つしか登録できません。
36 | * 決めたユニークなアプリケーション名を **(4)** に入力します - 例えば *IoTAssetTracker-yourname* のように。
37 | * **(5)** Create ボタンをクリック。
38 | 
39 | * IBM Cloud は、ボイラープレート内で定義されたサービスに基づいてアカウント内にアプリケーションを作成します。これはアプリケーションのステージングと呼ばれます。このプロセスが完了するまでに数分かかることがあります。待っている間は、`Logs` タブをクリックして、プラットフォームと Node.js ランタイムからのアクティビティログを見ることができます。
40 |
41 | ### IoT Starter アプリケーションの起動
42 |
43 | 緑の `Running` アイコン**(6)** が表示されたら、`Visit App URL` リンクをクリックします
44 | 
45 |
46 | ### Node-RED ビジュアル プログラミング エディタを開く
47 |
48 | 新しいブラウザタブが開き、Node-RED の開始ページが表示されます。
49 | Node-RED は、オープンソースの Node.js アプリケーションで、ビジュアルプログラミングエディタを備えており、フローを簡単に配線できます。
50 | Node-REDエディタにアクセスするには、ユーザ名とパスワードを選択します。
51 | あなたのユーザー名とパスワードを忘れないでください。
52 | 赤いボタンをクリックします。
53 | Node-RED フローエディタを選び、エディタを起動します。
54 |
55 | * Node-RED Visual Programming Editorがデフォルトのフローで開きます。
56 | * 左側には、フローにドラッグできるノードのパレットがあります。
57 | * ノードを結んでプログラムを作成することができます。
58 | * サンプル IoT スターターフローはこのワークショップでは使用しませんので、削除してかまいません。
59 | * 上で説明したフローをこれからインポートします。
60 |
61 | ### 追加の Node-RED ノードをインストールする
62 |
63 | IBM Cloud に導入された IoT スターター・アプリケーションには、Node-RED ノードのわずかなサブセットしか含まれていません。Node-RED パレットは、さまざまなデバイスや機能に合わせて1000個以上のノードを追加することで拡張できます。これらのNPMノードは http://flows.nodered.org で閲覧できます
64 |
65 | このステップでは、Node-RED Dashboard ノードを Internet of Things Starter アプリケーションに追加します。
66 |
67 | * 右上のNode-RED Menu **(1)** をクリックし、Manage palette **(2)** をクリックします。
68 | 
69 | * Install tab **(3)** を選択し、"node-red-dashboard" **(4)** と入力し、Install **(5)** ボタンをクリック。
70 | 
71 | * 次に表示されたダイアログでも Install ボタンをクリック。
72 | * 同様に **node-red-contrib-particle** と **node-red-contrib-web-worldmap** もインストールする。
73 |
74 | ### GitHub から事前に作成されたフローをインポートする
75 |
76 | Node-RED ノードを設定してそれらをまとめて配線するためには、スクリーンショットで文書化するための多くのステップが必要です。事前に作成されたフローを IoT スターターアプリケーションにインポートすることで、フローを簡単に作成できます。
77 |
78 | * 以降のセクションのいくつかには **コードを取得** のリンクがあります。
79 |
80 | * 指示があったら、**コードを取得** する GitHub URLを開き、マークを付けるか Ctrl-A を押してすべてのテキストを選択し、フローのテキストをクリップボードにコピーします。
81 |
82 | * Node-RED Menu **(6)** をクリックし、Import **(7)** をクリックし、Clipboard **(8)** をクリック。
83 | 
84 |
85 | * フローのテキストを **Import nodes** ダイアログにペーストし、赤い **Import** ボタンをクリック。
86 | 
87 |
88 | * 新しいフローは、Node-RED Editor の **新しいタブ** にインポートされます。
89 |
90 | ## 生鮮品のブロックチェーンと Node-RED フローを初期化する
91 |
92 | ### 前書き
93 |
94 | このフローは、他のすべてのフローを駆動するいくつかのグローバル変数を設定します。 Hyperledger Fabric IP アドレス、Particle Electron デバイスID、アクセストークンなどを変更するために他のフローを検索する代わりに、このフローではグローバル値として事前にプルしておき、残りのフローでは単にそれを利用します。
95 |
96 | * 自身の [Hyperledger Fabric](../Blockchain/README.md) を設定している場合は、**Set HyperLedgerFabricIP** Changeノードを編集し、パブリックIPアドレスを挿入します。
97 | * Particle Electron を購入した場合は、Particle デバイスIDとアクセストークンを知り、その詳細を **Particle Electron to Monitor** Changeノードに挿入する必要があります。
98 | * あなたがワークショップに参加している場合、インストラクターは Particle デバイスIDとアクセストークンを別のスライド (GitHubには含まれません) で共有します。
99 |
100 | 初期化フローでは、デモとワークショップを実行するために、以下で説明するほとんどすべてのフローに対してリンクノードを使用します。
101 | 
102 |
103 | 最初のステップとして、コードを GitHub からクリップボードにコピーし、Node-RED エディタにインポートしてみましょう。
104 |
105 | **コードを取得** [IoT Asset Tracker Node-RED flows](flows/IoTAssetTracker-AllFlows.json)
106 |
107 | ## Particle Electron イベントの制御
108 |
109 | ### 前書き
110 |
111 | このフローは、Particle Electron デバイスの構成を制御します。
112 | このフローは、デバイスの地理ロケーションレポートを有効または無効にするコマンドを送信できます。
113 | レポートの間隔を変更することができ、デフォルトは60秒です。
114 | また、Particle の2つの照会機能、GetRecentXYZ() と GetCurrTemp()も実行します。
115 | 加速度のしきい値は、SetXYZThresh() の呼び出しによってリモートで設定することもできます。
116 |
117 | Particle.io URL関数呼び出しは、アクセストークンを使用して特定のデバイスを制御します。
118 | 最初のタブの InitPerishableBlockchain フローにアクセストークンが設定されています。
119 | 講師はワークショップの後にこのアクセストークンをリセットします。
120 |
121 | このダッシュボードのインスピレーションは Hovig Ohannessian のものでした。
122 | 彼は、[Particle Core Bluemix article](https://www.ibm.com/blogs/bluemix/2015/05/led-hello-world-with-spark-core-android-bluemix/) を書きました。
123 | これはパラメーターを設定し、**httpリクエストノード** を使用して Particle 関数コマンドをポストするものです。
124 |
125 | 私は Node-RED Particle Function ノードも試しましたが、このユースケースでは柔軟性がありませんでした。
126 | フロー がParticle デバイスIDまたはアクセストークンを動的に設定できませんでした。
127 | ドロップダウンから選択可能な複数の Particle デバイスがある場合、Node-RED Particle Function ノードは特定のデバイスにハードコードされます。
128 | IoT 資産トラッカーのプロトタイプ作成には Particle Electron が1個しかないかもしれませんが、デプロイを開始するときには数十〜数百個になる可能性があります。
129 | 本番用のデプロイでは MQTT に切り替えることをお勧めします。
130 |
131 | 
132 | 
133 |
134 | ## Particle Electron イベントの受信
135 |
136 | ### 前書き
137 |
138 | Particle Receiver フローでは、**node-red-contrib-particle** ノードを使用します。ParticleSSE ノードを使用すると、永続的な接続を介して Particle クラウド上の着信サーバー受信イベント (SSE: Server-Sent Events) を購読できます。
139 |
140 | このフローには 4つの ParticleSSE() ノードがあります。
141 | それぞれは、InitPerishableBlockchain フローによって設定されたデバイスIDとアクセストークンを必要としています。
142 |
143 | * 最初の ParticleSSE() ノードは、Google Maps ジオロケーションイベントが有効になっていることを確認し、 Particular Electron の deviceLocator イベントにサブスクライブします。フローはこの情報で何もしません。これは単なる健全性のチェックです。
144 |
145 | * 一番下の ParticleSSE()ノードは、ジオロケーションイベント メッセージを解析して試します。 フローはこの情報で何もしません。
146 |
147 | * 間にある ParticlesSSE() ノードは、Particle Electron の AssetTrackerAccelerationEvent関数 と AssetTrackerTemperatureEvent 関数を購読しています - これらに関しては [WatsonIoTAssetTracker program のドキュメント](../ParticleElectron/README-ja.md) を見直してください。
148 | この情報は文字列から JSON オブジェクトに変換され、解析され、ブロックチェーン イベントに必要な msg.payload に再フォーマットされます。デバイスの GPS 座標が移動していない場合は、Exception ノードによる報告でイベントが破棄されます。この決定は単に、私が動作している装置のみの環境センサーの状態を気にしていたからです (そして、席に座って作業している間、テスト目的には、全てを扱うとデータ量が多すぎたので)。 実際の実装では、デバイスが流通センターの駐車場またはポートに置かれている間に温度と加速度のイベントが気になることがあります。 多くの場合、AssetTrackerAccelerationEvent 関数と AssetTrackerTemperatureEvent 関数は、deviceLocator コールバックによってほぼ同時にトリガーされます。 フローは、ブロックチェインがずらして少しずつ書き込むことで、Hyperledger Fabric に (書き込み障害を引き起こす可能性があるような) 大きな負荷をかけることが防ぎます。
149 |
150 |
151 | まとめると、このフローは到着するデータを取り込み、再フォーマットし、次のフローを呼び出して、Particle イベントを Hyperledger 生鮮品のネットワーク ブロックチェーンのトランザクション履歴に書き込みます。
152 |
153 | 
154 |
155 | ## Particle イベントを Hyperledger 生鮮品のネットワーク ブロックチェーンに書き込む
156 |
157 | ### 前書き
158 |
159 | このフローは、Hyperledger Perishable Network REST API を呼び出すための http パラメータを設定します。
160 | このワークショップの [Blockchain README](../Blockchain/README-ja.md) セクションで Hyperledger 生鮮品のネットワークモデルについて学んでください。
161 | このフローには6つの REST API の例があります。
162 |
163 | * 最初の REST API が SetupDemo API を呼び出します。これは一度だけ呼び出す必要があります。ブロックチェーンモデル [chaincode logic.js](../Blockchain/IoT-Perishable-Network/logic.js) の中に埋め込まれている場合、出荷IDとして Particle デバイスIDを挿入する必要がある setupDemo() 関数があります。
164 | * 2番目のセクションでは、トランザクションとして温度イベントをブロックチェーンに書き込むために必要な POST コマンドを設定します。
165 | * 3番目のセクションでは、ブロックチェーン上のすべての温度トランザクションを照会するために必要な GET コマンドを設定します。
166 | * 4番目のセクションでは、Acceleration イベントをトランザクションとしてブロックチェーンに書き込むために必要な POST コマンドを設定します。
167 | * 5番目のセクションでは、ブロックチェーン上のすべてのアクセラレーショントランザクションを照会するために必要な GET コマンドを設定します。
168 | * 6番目のセクションでは、トランザクションとしてジオロケーション イベントをブロックチェーンに書き込むために必要な POST コマンドを設定します。温度および加速度イベントには、関連付けられたジオロケーション座標があるため、このトランザクション履歴は使用されません。
169 |
170 | 
171 |
172 | ## 生鮮品のネットワーク ブロックチェーンのトランザクション履歴をロードする
173 |
174 | ### 前書き
175 |
176 | 生鮮品のネットワーク ブロックチェーンのトランザクション履歴をロードするフローは、このプログラムとワークショップの資産トラッカー ダッシュボード実装に固有のものになりそうです。温度ブロックチェーンのトランザクション履歴を照会し、加速度ブロックチェーンのトランザクション履歴を **配列** にマージし、マップを駆動します。
177 | 
178 |
179 |
180 | ## 資産トラッカーダッシュボードを開発する
181 |
182 | ### 前書き
183 |
184 | このフローは、IoT 環境センサーの読み取り値を収集しながら、デバイスの輸送 (トラック、車、船舶経由) が行ったルートの移動を選択および制御するためのさまざまな Node-RED Dashboard UI要素を構築します。Particle Electron 資産トラッカーデバイスは、異なる日に旅行をする可能性があるため、地図パスを絞り込む日付選択ツールがあります。マップ上にピンとジオフェンスを表示するための一連のフロー ロジックがあります。
185 | 
186 |
187 |
188 | ## 追跡されたデバイスをマップ上で移動する
189 |
190 | ### 前書き
191 |
192 | この最後のフローは、選択された Particle Electron IoT 資産トラッカーデバイスの移動中にその動きを駆動します。1秒に1回、マップ上のデバイスを進めます。これは、選択されたデバイスと時間枠で配列をフィルタリングします。これらの配列を管理するより良い方法があるかもしれません。数十のルートの後で、おそらく縮尺は変わっていないでしょう。それは素晴らしいデモとワークショップになります。 常に企業スケールでの規模の改善の余地があります。楽しみましょう!
193 | 
194 |
195 | ## おめでとうございます! これでこの IBM コードパターンのワークショップは完了です
196 |
197 | あなたは、Hyperledger Blockchain にデータを格納する環境センサーを備えた IoT 資産トラッカーを構築しました。
198 | 
199 |
--------------------------------------------------------------------------------
/Node-RED/README.md:
--------------------------------------------------------------------------------
1 | *Read this in other languages: [日本語](README-ja.md).*
2 |
3 | # Node-RED - IoT Asset Tracker
4 | ## Node-RED - IoT Asset Tracker Introduction
5 |
6 | 
7 |
8 | These Node-RED program flows implement an IoT Asset Tracker that receives geolocation and environmental sensor data from a Particle Electron, stores that information in a Hyperledger Fabric blockchain and visualizes the routes of the IoT devices on a map / dashboard. It triggers alerts when environmental thresholds are exceeded.
9 |
10 | During this workshop you will copy the flow from github and deploy it into your to Watson IoT / Node-RED Starter application running on IBM Cloud.
11 |
12 | These seven flows perform the following functions:
13 |
14 | * **Initialize Blockchain and Node-RED variables** - Set some globals that drive all of the flows.
15 | * **Control a Particle Electron** - A Node-RED Dashboard which enables / disables / configures a Particle Electron.
16 | * **Receive Particle Electron events** - subscribe to Particle Electron event handlers.
17 | * **Write Particle Electron data** to a Hyperledger Fabric Blockchain.
18 | * **Load Blockchain Transaction History** so the IoT device routes can be plotted
19 | * **Build a Dashboard** that controls the visualization of devices.
20 | * **Move a IoT asset along its recorded history** by visualizing the route on a map.
21 |
22 | The dashboards are not intended to be a fancy user experience for end users. These dashboards are demonstrations for a developer of what an IoT Asset Tracker might be capable of. End users are not likely to be interested in geolocation coordinates.
23 |
24 | ## Getting started with Node-RED in the IBM Cloud
25 | Before you can deploy the IoT Asset Tracker dashboard, you need to create an IoT Starter application in the IBM Cloud. This section walks you through those steps.
26 | ### Create an Internet of Things Starter App
27 | * Create an account and log into [IBM Cloud](http://bluemix.net)
28 | * Click on the Catalog **(1)** and search for 'internet of things' **(2)**
29 | * The Internet of Things Platform Starter **(3)** boilerplate is a pattern with pre-assembled services that work together. The Internet of Things Platform Starter includes a Node-RED Node.js web server, Cloudant database to store the flow, and the IoT platform service so you can connect devices.
30 | 
31 | * Name your application something unique. If you choose myapp, your application will be located at http://myapp.mybluemix.net There can only be one “myapp” application and URL registered in IBM Cloud.
32 | * Give the application a unique name **(4)** - eg. IoTAssetTracker-yourname
33 | * Press the Create button **(5)**.
34 | 
35 | * IBM Cloud will create an application in your account based on the services in the boilerplate. This is called staging an application. It can take a few minutes for this process to complete. While you wait, you can click on the Logs tab and see activity logs from the platform and Node.js runtime.
36 |
37 | ### Launch the IoT Starter Application
38 | Once the Green “Running” icon appears, Click the Visit App URL link **(6)**
39 | 
40 |
41 | ### Open the Node-RED visual programming editor
42 | A new browser tab will open to the Node-RED start page. Node-RED is an open-source Node.js application that provides a visual programming editor that makes it easy to wire together flows. Select a username / password to access the Node-RED editor. Remember your username / password. Click the red button. Go to your Node-RED flow editor to launch the editor.
43 | * The Node-RED Visual Programming Editor will open with a default flow.
44 | * On the left side is a palette of nodes that you can drag onto the flow.
45 | * You can wire nodes together to create a program.
46 | * The sample IoT Starter flow is not applicable to this workshop and can be deleted.
47 | * We will import the flows discussed above.
48 |
49 | ### Install Additional Node-RED nodes
50 | The IoT Starter Application deployed into IBM Cloud includes just a small subset of Node-RED nodes. The Node-RED palette can be extended with over one thousand additional nodes for different devices and functionality. These NPM nodes can be browsed at http://flows.nodered.org
51 |
52 | In this Step, you will add the Node-RED Dashboard nodes to your Internet of Things Starter Application.
53 | * Click on the Node-RED Menu **(1)** in the upper right corner, then Manage palette **(2)**
54 | 
55 | * Turn to the Install tab **(3)**, type node-red-dashboard **(4)** and press the Install button **(5)**.
56 | 
57 | * Press the Install button in the next dialog.
58 | * Repeat **(4)** to install **node-red-contrib-particle** and **node-red-contrib-web-worldmap** nodes.
59 |
60 | ### Import a prebuilt flow from GitHub
61 | Since configuring Node-RED nodes and wiring them together requires many steps to document in screenshots, there is an easier way to build a flow by importing a prebuilt flow into your IoT Starter Application.
62 |
63 | * Some of the sections below will have a **Get the Code** link.
64 |
65 | * When instructed, open the **Get the Code** github URL, mark or Ctrl-A to select all of the text, and copy the text for the flow to your Clipboard.
66 | * Click on the Node-RED Menu **(6)**, then Import **(7)**, then Clipboard **(8)**.
67 | 
68 | * Paste the text of the flow into the **Import nodes** dialog and press the red **Import** button.
69 | 
70 | * The new flow will be imported into **new tabs** in the Node-RED Editor.
71 |
72 | ## Initialize the Perishable Blockchain / Node-RED flow
73 | ### Introduction
74 | This flow sets several global variables that drive all of the other flows. Instead of hunting through the other flows to modify the Hyperledger Fabric IP address or your Particle Electron Device ID and access token, this flow simply pulls the globals forward and initializes the remaining flows.
75 |
76 | * If you have set up your [Hyperledger Fabric](../Blockchain/README.md), edit the **Set HyperLedgerFabricIP** change node and insert the public IP address.
77 | * If you purchased your own Particle Electron, you will need to know the Particle Device ID and Access Token and insert those details into the **Particle Electron to Monitor** change node.
78 | * If you are participating in a workshop, the instructor will share the Particle Device ID and Access Token in a separate slide (not part of GitHub)
79 |
80 | The Initialization flow then uses Link nodes to most all of the other flows described below to drive the demo and workshop.
81 | 
82 |
83 | As a first step, copy the code from GitHub to your Clipboard and import it into your Node-RED editor.
84 |
85 | Get the Code [IoT Asset Tracker Node-RED flows](flows/IoTAssetTracker-AllFlows.json)
86 |
87 | ## Control Particle Electron events
88 | ### Introduction
89 | This flow controls the Particle Electron device configuration. This flow can send a command to enable / disable the device geolocation reporting. It can change the interval of the report. The default is 60 seconds. It also exercises the two query Particle Functions - GetRecentXYZ() and GetCurrTemp(). The acceleration threshold can also be remotely configured through a call to SetXYZThresh().
90 |
91 | The Particle.io URL function calls use a AccessToken to control a particular device. The AccessToken is set in the InitPerishableBlockchain flow (on the first tab) The instructor will reset this access token after the workshop.
92 |
93 | The inspiration for this dashboard came from Hovig Ohannessian. He wrote a [Particle Core Bluemix article](https://www.ibm.com/blogs/bluemix/2015/05/led-hello-world-with-spark-core-android-bluemix/)
94 | that sets up the params and uses a **http request node** to post the Particle function command.
95 |
96 | I also experimented with the Node-RED Particle Function nodes but I found them inflexible in this use case. The flow could not dynamically set the Particle Device ID or AccessToken. When there are multiple Particle devices selectable from the drop down, the Node-RED Particle Function nodes are hard coded to specific devices. While you might only have one Particle Electron for prototyping an IoT Asset Tracker, when you start a deployment, you might have dozens / hundreds. I would recommend switching to MQTT for production deployments.
97 |
98 | 
99 | 
100 |
101 | ## Receive Particle Electron events
102 | ## Introduction
103 | The Particle Receiver flow uses the **node-red-contrib-particle** nodes. The ParticleSSE node lets you subscribe to incoming server-sent events (SSE) on a Particle cloud via a persistent connection.
104 |
105 | There are four ParticleSSE() nodes on this flow. Each needs to be configured with a Device ID and an AccessToken - set by the InitPerishableBlockchain flow.
106 | * The first ParticleSSE() node just confirms that there is a Google Maps geolocation Event enabled and subscribes to the deviceLocator event on a particular Electron. The flow doesn't do anything with this information. It's just a sanity check.
107 | * The bottom ParticleSSE() node experiments with parsing the geolocation event message. The flow doesn't do anything with this information.
108 | * The middle ParticleSSE() nodes subscribe to the AssetTrackerAccelerationEvent and AssetTrackerTemperatureEvent functions of our Particle Electron - review the [WatsonIoTAssetTracker program here](../ParticleElectron/README.md). This information is converted from a string to a JSON object, parsed and reformatted into a msg.payload that is expected for a Blockchain event. If the device GPS coordinates have not moved, discard the event by using a Report By Exception node. This decision was simply because I only care about the environmental sensor conditions of the device in motion (and it was filling my blockchain while sitting on my desk). A real implementation might care about temperature and acceleration events while the device sits in a distribution center parking lot or port. Often the AssetTrackerAccelerationEvent and AssetTrackerTemperatureEvent functions are triggered nearly simultaneously by the deviceLocator callback. The flow staggers the blockchain writes a little to avoid overwhelming the Hyperledger Fabric (which could cause a write failure).
109 |
110 | In summary, this flow takes the arriving data, reformats it and calls the next flow to write the Particle Events to the Hyperledger Perishable Network blockchain transaction history.
111 | 
112 |
113 | ## Write Particle Events to Hyperledger Perishable Network Blockchain
114 | ### Introduction
115 | This flow sets up the http parameters to call the Hyperledger Perishable Network REST APIs. Learn about the Hyperledger Perishable Network model in the [Blockchain README](../Blockchain/README.md) section of this workshop / IBM Code pattern. There are six REST API examples in this flow.
116 | * The first REST API calls the SetupDemo API. This only needs to be called once. Buried deep in the Blockchain Model [chaincode logic.js](../Blockchain/IoT-Perishable-Network/logic.js), there is a setupDemo() function where you will need to insert your Particle Device ID as the Shipment ID
117 | * The second section sets up the POST command required to write a Temperature event into the blockchain as a transaction.
118 | * The third section sets up the GET command required to query all of the Temperature transactions on the blockchain.
119 | * The fourth section sets up the POST command required to write an Acceleration event into the blockchain as a transaction.
120 | * The fifth section sets up the GET command required to query all of the Acceleration transactions on the blockchain.
121 | * The sixth section sets up the POST command required to write a geolocation event into the blockchain as a transaction. The flow does not use this transaction history because the Temperature and Acceleration events have geolocation coordinates associated with them.
122 | 
123 |
124 | ## Load Perishable Network Blockchain Transaction History
125 | ### Introduction
126 | The Load Perishable Network Blockchain Transaction History flow starts to become specific to the Asset Tracker dashboard implementation of this program and workshop. It queries the Temperature blockchain transaction history and then merges the Acceleration blockchain transaction history into an **array** that will drive the map.
127 | 
128 |
129 |
130 | ## Build an Asset Tracking Dashboard
131 | ### Introduction
132 | This flow constructs a variety of Node-RED Dashboard UI elements to select and control the movement of the routes that the device shipment (via trucks, cars, ships) took while collecting IoT environmental sensor readings. A Particle Electron asset tracking device might take trips on different days so there is a date picker to narrow the map paths. There is a bunch of flow logic to display pins and geo fences on the map.
133 | 
134 |
135 |
136 | ## Move the Tracked Device on a Map
137 | ### Introduction
138 | This final flow drives the movement of a selected Particle Electron IoT AssetTracker device during its journey. Every fraction of a second, it advances the device on a map. It filters the array down to the selected device and time frame. There might be better ways to manage these arrays. After a few dozen routes, it probably doesn't scale. It makes for a great demo and workshop. There's always room for enterprise scale improvements. Enjoy!
139 | 
140 |
141 | ## Congratulations! You have completed the Workshop / IBM Code Pattern
142 | You've built an IoT Asset Tracker with environmental sensors that store data in a Hyperledger Blockchain.
143 | 
144 |
--------------------------------------------------------------------------------
/Node-RED/screenshots/IBMCloud-Catalog-newstarter-annotated.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/IBMCloud-Catalog-newstarter-annotated.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/IBMCloud-NodeRED-CFappcreate.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/IBMCloud-NodeRED-CFappcreate.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/IBMCloud-NodeRED-import.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/IBMCloud-NodeRED-import.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/IBMCloud-NodeRED-launch.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/IBMCloud-NodeRED-launch.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/IBMCloud-NodeRED-nodeinstall.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/IBMCloud-NodeRED-nodeinstall.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/IBMCloud-NodeRED-palette.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/IBMCloud-NodeRED-palette.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/IBMCloud-NodeRED-pastefromclipboard.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/IBMCloud-NodeRED-pastefromclipboard.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/Node-RED-dashboard-AssetTracker-NJ.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/Node-RED-dashboard-AssetTracker-NJ.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/Node-RED-dashboard-AssetTracker-PR.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/Node-RED-dashboard-AssetTracker-PR.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/Node-RED-dashboard-ControlParticleDevice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/Node-RED-dashboard-ControlParticleDevice.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/Node-RED-flow-AssetTrackerDashboardControls.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/Node-RED-flow-AssetTrackerDashboardControls.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/Node-RED-flow-AssetTrackerMap.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/Node-RED-flow-AssetTrackerMap.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/Node-RED-flow-ControlParticleDevice.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/Node-RED-flow-ControlParticleDevice.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/Node-RED-flow-InitPerishableBlockchain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/Node-RED-flow-InitPerishableBlockchain.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/Node-RED-flow-LoadBlockchainTransactionHistory.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/Node-RED-flow-LoadBlockchainTransactionHistory.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/Node-RED-flow-ReceiveParticleEvents.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/Node-RED-flow-ReceiveParticleEvents.png
--------------------------------------------------------------------------------
/Node-RED/screenshots/Node-RED-flow-WriteParticleEvents2Blockchain.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/Node-RED/screenshots/Node-RED-flow-WriteParticleEvents2Blockchain.png
--------------------------------------------------------------------------------
/ParticleElectron/README-ja.md:
--------------------------------------------------------------------------------
1 | *Read this in other languages: [English](README.md).*
2 |
3 | # Particle Electron 資産トラッカー
4 |
5 | Particle Electron 資産トラッカーを使用すると、環境センサーデータを収集し、GPSまたはセルラー三角測量を使用してその位置を計算し、両方のデータイベントを Particle Functions を使用して Particle.io コンソールに送信することができます。
6 | 物理的なものが過酷な環境条件にさらされた時、**Where、What、When** の情報を知ることにより、多くのビジネスプロセスを改善することができます。
7 |
8 | このセクションでは以下を確認します:
9 | * Particle Electron 資産トラッカーのハードウェア構成
10 | * Particle ソフトウェア ツールチェーン
11 | * Watson IoT Asset Tracker プログラムは、温度と加速度計のデータを問い合わせ、クラウドに報告します
12 |
13 | ## Particle Electron Asset Tracker v2
14 | 
15 |
16 | [Particle Electron Asset Tracker v2](https://store.particle.io/products/asset-tracker) ボードでは、uBlox M8 GNSS GPS レシーバーと Adafruit LIS3DH Triple Axis 加速度計を Particle Electron に接続することができます。
17 | Grove センサーを接続することもできます。
18 |
19 | ## Particle Electron ソフトウェア ツールチェーン
20 | 1. http://login.particle.io/ サイトで自身の Particle.io アカウントを設定する。
21 | 2. 自身の Particle Electron を起動し名前をつける。
22 | * 私の Electron は `blockchain-iot-asset-tracker1` です。
23 | 3. SIM を起動する。
24 | 4. 自身の Particle Electron を登録すると、[Particle Devices Console](https://console.particle.io/devices) に表示される。
25 | 5. Particle.io の提供する [Particle Build WebIDE](https://docs.particle.io/guide/getting-started/build/core/) か CLI コマンドライン toolchain を使用する。
26 | 6. 私は [WebIDE](https://build.particle.io/) に関して以下のサンプルを使用して少し学びました:
27 | * LEDをブレッドボードに配線し、blink-led プログラムで点滅させてみた
28 | * ウェブ接続の LED サンプルアプリケーションを試してみた
29 | * Cloud2LED.bin を変更して Particle クラウドから LED の On/Off を Electron に送信してみた。
30 | 私はそれを大文字と小文字を区別しないよう、"on/off" と "ON/OFF" を共に認識するよう簡単な改造をしてみました!
31 |
32 | 7. [Particle Functions](https://docs.particle.io/reference/firmware/core/#particle-function-) を読むと、イベントを公開して購読できるようになります。
33 | 8. 私は Web IDE よりコマンドラインインターフェースを好むので、ガイドに従って、[Particle CLI]( https://docs.particle.io/guide/tools-and-features/cli/electron/) をインストールしました。
34 | ```
35 | $ particle login
36 | $ particle upgrade
37 | ```
38 | [ファームウェアのアップグレード](https://docs.particle.io/guide/tools-and-features/firmware-manager/electron/) は、Google Map ジオロケーションデバイスのロケータを機能させるために重要でした。私の Particle Electron は v0.4.9 が工場出荷時にインストールされていましたが、v0.6.4にアップグレードすると Google Maps 機能が機能するようになりました。
39 |
40 | 9. 次のステップとして [particle compile]( https://docs.particle.io/reference/cli/#particle-compile) コマンドを学びます。
41 | ```
42 | $ particle compile
43 | ```
44 | 私の場合は:
45 | ```
46 | $ particle compile electron WatsonIoTAssetTracker --saveTo WatsonIoTAssetTracker.bin
47 | ```
48 | 10. あなたの Particle プロジェクトで利用できる多くの Arduino 用の [Particle ライブラリ](https://docs.particle.io/guide/tools-and-features/libraries/) があります。
49 | ```
50 | $ particle library list
51 | $ particle library view AssetTracker
52 | $ particle library view OneWire
53 | ```
54 | 11. あなたの Particle Electron を書き換えるためには、 [dfu-util](https://docs.particle.io/faq/particle-tools/installing-dfu-util/core/) をインストールする必要があります。私は Fedora 25 リポジトリにある *dfu-util-0.9-1.fc25.x86_64.rpm* を使用しました。
55 | 12. Electron のリセットボタンとモードボタンを押したままにして
56 | * リセットボタンをはなす
57 | * LEDが黄色になるのを待つ
58 | * モードボタンをはなす
59 | 13. 最後に、次のコマンドを使用してプログラムをボードに書き込みます:
60 | ```
61 | $ particle flash --usb firmware.bin
62 | ```
63 | 私の場合は:
64 | ```
65 | $ particle flash --usb WatsonIoTAssetTracker.bin
66 | ```
67 | 14. プログラムが何をしているかを見るには、[Particle serial](https://docs.particle.io/reference/firmware/photon/#serial) 出力を監視するようにUSBケーブルを設定します。rickkas7 が素晴らしい [Particle serial チュートリアル](https://github.com/rickkas7/serial_tutorial) を書きました。
68 | ```
69 | $ particle serial monitor
70 | ```
71 |
72 | ## Watson IoT Asset Tracker プログラム
73 |
74 | このリポジトリにある Watson IoT Asset Tracker プログラムの実装を見てみましょう。温度と加速度計のデータを要求し、その位置とともにクラウドに報告します。
75 |
76 | このリポジトリで [WatsonIoTAssetTracker.ino](WatsonIoTAssetTracker.ino) コードを取得し、以下のレビューに従ってください。
77 | これは [Particle Simple project](https://docs.particle.io/guide/tools-and-features/libraries/#project-file-structure) ですので、[project.properties](project.properties) ファイルもリポジトリからダウンロードする必要があります。これには、プログラムをコンパイルするために必要なライブラリのリストが含まれています。
78 |
79 | > 訳注: INO ファイルは Arduino Sketch File 形式で、Arduino ベースの IoT 機器上で動作するプログラムです。
80 |
81 | ### ```void setup()```
82 |
83 | この Arduino プログラムのもっとも興味深いのは ``setup()`` で、温度と加速度センサーのデータを送信して問い合わせる4つの Particle 関数を宣言しています。
84 |
85 | ``` C
86 | // Declare a Particle.function so that we can adjust the Asset Tracking on and off reporting interval from the cloud.
87 | Particle.function("SetInterval",AssetTrackerSetReportInterval);
88 |
89 | // Declare a Particle.function so that we can query the current temperature from the cloud.
90 | Particle.function("GetCurrTemp",AssetTrackerGetCurrentTemp);
91 |
92 | // Declare a Particle.function so that we can adjust the accelerometer threshold from the cloud.
93 | Particle.function("SetXYZThresh",AssetTrackerSetAccelThresh);
94 |
95 | // Declare a Particle.function so that we can query recent accelerometer data from the cloud.
96 | Particle.function("GetRecentXYZ",AssetTrackerGetRecentAccel);
97 | ```
98 |
99 | このプログラムの次の興味深い点は、[Google Maps Locator API](https://docs.particle.io/tutorials/integrations/google-maps/) を使用して、Cellular タワーの信号強度に基づいて地理的位置を三角測量することです。
100 | Google は、Cellular タワーの位置 (ヒント: タワーは移動せず、地面に固定されています) を把握しており、タワーからあなたのデバイスまでの信号の RSSI 強度から、そのおおよその位置を計算することができます。
101 | 都合の良いことに、Particle Electron にはSIMカードがあり、携帯電話網を介して通信することができます。
102 |
103 | Asset Trackerボードで GPS を使用するのは素晴らしいことですが、遮られることもなく、GPS衛星と常に直線的な通信ができる状態を常に保つことは困難でしょう。
104 | また GPS チップセットはかなりのバッテリー電力を消費するので、トラッカーの稼働時間を短くしてしまうでしょう。
105 | 実際、Cellular による三角測量はGPSほど正確ではありません。
106 | しかし、高速道路を走行する際に「どこにいるの?」という質問に答えるほとんどのケースでは、数百メートルの半径で十分なことがほとんどです。
107 | 私は個人的に [Google Maps API Key](https://developers.google.com/maps/documentation/geolocation/get-api-key) を持っています。
108 | これは CellularHelper ライブラリを使用しています。
109 |
110 | ```
111 | $ particle library view CellularHelper
112 | $ particle library view google-maps-device-locator
113 | ```
114 |
115 | ### 機能
116 |
117 | プログラムは4つの Particle Function コールバックとヘルパー関数を実装して、加速度センサーと温度センサーを照会します。
118 |
119 | 注目すべきは、もっと洗練された実装でしたが、私は [Grove 温度センサー](http://wiki.seeed.cc/Grove-Temperature_Sensor_V1.2/) を AssetTracker ボードの Grove コネクタと連携させることができませんでした。
120 | 私はいくつかの古き良き Dallas DS18B20 温度センサーを注文しました。
121 | 私は、これらの [チュートリアルの指示](https://docs.particle.io/tutorials/projects/maker-kit/#tutorial-4-temperature-logger) に従って、それらの1つ (と1つの抵抗器) を私の Particle Electron に配線しました。
122 | これは OneWire ライブラリを使用します。
123 |
124 | ### プログラム ロジック
125 |
126 | プログラムは、その場所に応じて設定した間隔で定期的に起動します。
127 | これにより、DeviceLocator イベントがトリガーされます。
128 | Cellular タワーの信号強度を照会し、RSSI データを Google Maps API に送信した後、地理的位置の緯度/経度/確度など座標情報をボードに返信します。
129 | プログラムが座標情報を取得すると、温度を読み取り、加速度計がモーション閾値を超えているかどうかをチェックします。
130 | その後、Particleコールバック関数 *AssetTrackerLocationCallback()* によって3つのデータポイント(**WHERE、WHAT、WHEN**)をクラウドに送信します。
131 | この情報の組み合わせは **IoT 資産トラッカー** の基礎です。
132 |
133 | それをまとめてみると、このように見えます。
134 | 
135 |
136 | また、提供された Particle 資産トラッカーのケースにうまく収まります:
137 | 
138 |
139 | ### クラウドプログラムを有効化して Particle Function コールバックを受け取る
140 |
141 | 最初にデータが Particle コンソールに届くと、あなたはとても喜ぶでしょう。
142 | ここに、[Particle.io](https://console.particle.io/devices) クラウドに到着する温度データ、加速度計データ、および地理位置データのスクリーンショットがあります。
143 |
144 | 
145 |
146 | あなたが本当にやりたいことは、そのデータをどこか別の場所に送ることです。
147 | 私の場合、IoT データを IBM Cloud および Node-RED にルーティングして、Hyperledger Fabricブロックチェーンに格納する必要があります。
148 | [次のセクション](../Blockchain/README-ja.md) もしくは [Node-REDのセクション](../Node-RED/README-ja.md) にジャンプします。
149 |
150 |
151 |
152 | 移動する前に、Node-RED プログラムがこれらのセンサーイベントを監視/購読することを許可する Particle トークンが必要です。
153 |
154 | ```
155 | $ particle token list
156 | $ particle token new
157 | ```
158 | ターミナルから以下のコマンドでデータを参照することができます:
159 | ```
160 | $ curl https://api.particle.io/v1/devices/events?access_token=
161 | ```
162 |
--------------------------------------------------------------------------------
/ParticleElectron/README.md:
--------------------------------------------------------------------------------
1 | *Read this in other languages: [日本語](README-ja.md).*
2 |
3 | # Particle Electron Asset Tracker
4 | The Particle Electron Asset Tracker can be used to collect environmental sensor data, calculate its location using GPS or Cellular triangulation and send both data events to the Particle.io console using Particle Functions. The power of knowing **Where, What and When** physical things were subjected to harsh environmental conditions can improve many business processes.
5 |
6 | In this section we will review :
7 | * Particle Electron Asset Tracker hardware configuration
8 | * Particle software toolchain
9 | * A Watson IoT Asset Tracker program to query and report temperature and accelerometer data to the cloud.
10 |
11 | ## Particle Electron Asset Tracker v2
12 | 
13 |
14 | The [Particle Electron Asset Tracker v2](https://store.particle.io/products/asset-tracker) board allows you to connect a Particle Electron with its uBlox M8 GNSS GPS receiver and Adafruit LIS3DH Triple Axis Accelerometer. You can connect Grove Sensors to it as well.
15 |
16 | ## Particle Electron software toolchain
17 | 1. Set up your Particle.io Account at http://login.particle.io/
18 | 2. Activate your Particle Electron and give it a name. I called my Electron - blockchain-iot-asset-tracker1
19 | 3. Activate the SIM
20 | 4. After I registered my Particle Electron, it appeared in the [Particle Devices Console](https://console.particle.io/devices)
21 | 5. Particle.io provides a [Particle Build WebIDE](https://docs.particle.io/guide/getting-started/build/core/) or a CLI command line toolchain.
22 | 6. I spent some time learning the [WebIDE](https://build.particle.io/) by playing with the samples:
23 | * Wire a LED to the breadboard using the blink-led program
24 | * Web Connected LED sample app
25 | * I modified the Cloud2LED.bin to send LED on/off from Particle cloud down to Electron. I modified it to support case insensitive "on/off" and "ON/OFF" - baby steps!
26 | 7. It's worth reading about [Particle Functions](https://docs.particle.io/reference/firmware/core/#particle-function-) so that you can publish and subscribe to events.
27 | 8. Since I prefer a command line interface over a Web IDE, I installed the [Particle CLI]( https://docs.particle.io/guide/tools-and-features/cli/electron/) by following the guide.
28 | ```
29 | $ particle login
30 | $ particle upgrade
31 | ```
32 | The [firmware upgrade](https://docs.particle.io/guide/tools-and-features/firmware-manager/electron/) was important to get the Google Maps geolocation device locator working. My Particle Electron was factory installed with v0.4.9, once I upgraded to v0.6.4, the Google Maps function finally worked.
33 |
34 | 9. The next step was to learn about the [$ particle compile]( https://docs.particle.io/reference/cli/#particle-compile) command
35 | ```
36 | $ particle compile
37 | ```
38 | In my case:
39 | ```
40 | $ particle compile electron WatsonIoTAssetTracker --saveTo WatsonIoTAssetTracker.bin
41 | ```
42 | 10. There are lots of Arduino / [Particle libraries](https://docs.particle.io/guide/tools-and-features/libraries/) which you can include in your Particle projects.
43 | ```
44 | $ particle library list
45 | $ particle library view AssetTracker
46 | $ particle library view OneWire
47 | ```
48 | 11. To flash your Particle Electron, you need to install [dfu-util](https://docs.particle.io/faq/particle-tools/installing-dfu-util/core/).
49 | I grabbed a copy of *dfu-util-0.9-1.fc25.x86_64.rpm* from the Fedora 25 repo.
50 | 12. Hold down both the Reset and Mode buttons on the Electron
51 | * Release the Reset button
52 | * Wait for the LED to turn Yellow
53 | * Release the Mode button
54 | 13. Finally flash your program to the board using the next command
55 | ```
56 | $ particle flash --usb firmware.bin
57 | ```
58 | In my case:
59 | ```
60 | $ particle flash --usb WatsonIoTAssetTracker.bin
61 | ```
62 | 14. To watch what the program is doing, you can set up the USB cable to monitor the [Particle serial](https://docs.particle.io/reference/firmware/photon/#serial) output. I found that rickkas7 wrote a great [Particle serial tutorial](https://github.com/rickkas7/serial_tutorial)
63 | ```
64 | $ particle serial monitor
65 | ```
66 |
67 | ## Watson IoT Asset Tracker program
68 | Let's review the Watson IoT Asset Tracker program implementation found in this repository. It queries and reports temperature and accelerometer data to the cloud along with its location.
69 |
70 | Grab the [WatsonIoTAssetTracker.ino](WatsonIoTAssetTracker.ino) code in this repo to follow along in the review. This is a [Particle Simple project](https://docs.particle.io/guide/tools-and-features/libraries/#project-file-structure) so you will also need to download the [project.properties](project.properties) file from the repo. It includes a list of libraries necessary for the program to compile.
71 |
72 | ### ```void setup()```
73 |
74 | The most interesting aspect of this Arduino program is that in ```setup()``` I declare four Particle functions to send and query temperature and accelerometer sensor data.
75 | ``` C
76 | // Declare a Particle.function so that we can adjust the Asset Tracking on and off reporting interval from the cloud.
77 | Particle.function("SetInterval",AssetTrackerSetReportInterval);
78 |
79 | // Declare a Particle.function so that we can query the current temperature from the cloud.
80 | Particle.function("GetCurrTemp",AssetTrackerGetCurrentTemp);
81 |
82 | // Declare a Particle.function so that we can adjust the accelerometer threshold from the cloud.
83 | Particle.function("SetXYZThresh",AssetTrackerSetAccelThresh);
84 |
85 | // Declare a Particle.function so that we can query recent accelerometer data from the cloud.
86 | Particle.function("GetRecentXYZ",AssetTrackerGetRecentAccel);
87 | ```
88 |
89 | The next most interesting thing about the program is that it uses the [Google Maps Locator API](https://docs.particle.io/tutorials/integrations/google-maps/) to triangulate its geo location based on Cellular tower signal strength. Google knows where the cell towers are (hint - they don't move and are cemented to the ground) and the RSSI strength of the signals from the towers to your thing, its a math calculation to approximate your things' location. Nice that the Particle Electron has a SIM card and communicates over the cellular network. While it's great to use the GPS on the Asset Tracker board, often the thing you want to track is deep in a truck or a car or ship without clear line of sight to the Global Navigation Satellite System - rendering GPS useless. The GPS chipset also draws substantial battery power that would be better used to increase the tracker's time between charges. In truth, cellular triangulation is not as accurate as GPS. For most cases of answering "where's the thing" as it drives down the highway, a few hundred meter radius is plenty good enough. I got myself a [Google Maps API Key](https://developers.google.com/maps/documentation/geolocation/get-api-key) It uses the CellularHelper library.
90 | ```
91 | $ particle library view CellularHelper
92 | $ particle library view google-maps-device-locator
93 | ```
94 | ### Functions
95 | The program proceeds to implement the four Particle Function callbacks and the helper functions to query the accelerometer and temperature sensors.
96 |
97 | Of note, while it would have been a much cleaner implementation, I could not get the [Grove Temperature sensor](http://wiki.seeed.cc/Grove-Temperature_Sensor_V1.2/) to work with the Grove connectors on the AssetTracker board. I ordered some good old Dallas DS18B20 temperature sensors. I wired one of them (and a resistor) to my Particle Electron following these [tutorial instructions](https://docs.particle.io/tutorials/projects/maker-kit/#tutorial-4-temperature-logger). It uses the OneWire library.
98 |
99 | ### Program Logic
100 | The program wakes up periodically on an interval you set to determine its location. That triggers a DeviceLocator event. After querying cellular tower signal strengths and sending the RSSI data to the Google Maps API, it responds back to the board with geolocation latitude / longitude / uncertainty coordinates. When the program gets the geolocation, it reads the temperature and checks if the accelerometer has exceeded a motion threshold. It then sends three datapoints - **WHERE, WHAT and WHEN** - to the cloud via the Particle callback function *AssetTrackerLocationCallback()* The combination of that information is the basis of an **IoT Asset Tracker**.
101 |
102 | Put it all together and it looks like this.
103 | 
104 |
105 | It also fits nicely into the provided Particle Asset Tracker case:
106 | 
107 |
108 |
109 | ### Enabling your Cloud Programs to intercept your Particle Function callbacks
110 | You'll be all giddy the first time data arrives in the Particle Console. Here's a screenshot of temperature data, accelerometer data and geolocation data arriving in the [Particle.io](https://console.particle.io/devices) cloud.
111 | 
112 |
113 | What you really want to do is send that data somewhere else. In my case, I want to route the IoT data to the IBM Cloud and Node-RED for storage in a Hyperledger Fabric blockchain. Jump to the next [section](../Node-RED/README.md).
114 |
115 | Before you go, you'll need a Particle token to authorize your Node-RED program to observe / subscribe to these sensor events.
116 | ```
117 | $ particle token list
118 | $ particle token new
119 | ```
120 | You can see the data in your terminal
121 | ```
122 | $ curl https://api.particle.io/v1/devices/events?access_token=
123 | ```
124 |
--------------------------------------------------------------------------------
/ParticleElectron/WatsonIoTAssetTracker.ino:
--------------------------------------------------------------------------------
1 | // Library dependencies to be added to the Particle Simple project.properties
2 | // dependencies.Adafruit_LIS3DH=1.0.3
3 | // dependencies.Adafruit_GPS=1.0.3
4 | // dependencies.AssetTracker=0.0.10
5 | // dependencies.CellularHelper=0.0.4
6 | // dependencies.OneWire=2.0.1
7 | // dependencies.Adafruit_Sensor=1.0.2
8 | // dependencies.google-maps-device-locator=0.0.4
9 | #include
10 | #include
11 | #include
12 |
13 | // Dallas DS18B20 initialization
14 | OneWire ds = OneWire(D4); // 1-wire signal on pin D4
15 | float lastTemp;
16 |
17 | // Adafruit LIS3DH Triple Axis Accelerometer on the Particle Asset Tracker v2 PCB
18 | // Accelerometer Threshold to trigger a publish
19 | // 9000 is very sensitive, 12000 will detect small bumps
20 | int AccelThreshold = 12000;
21 | String MaxAccelJSON;
22 | int MaxAccelThisInterval = 0;
23 |
24 | // Creating an AssetTracker named 't'
25 | GoogleMapsDeviceLocator locator;
26 | AssetTracker t = AssetTracker();
27 | int ledonboard = D7; // Light the onboard Particle LED when in Tracking mode
28 |
29 | void setup() {
30 | // Sets up all the necessary AssetTracker bits
31 | t.begin();
32 |
33 | Serial.begin(9600);
34 |
35 | // Declare a Particle.function so that we can adjust the Asset Tracking on and off reporting interval from the cloud.
36 | Particle.function("SetInterval",AssetTrackerSetReportInterval);
37 |
38 | // Declare a Particle.function so that we can query the current temperature from the cloud.
39 | Particle.function("GetCurrTemp",AssetTrackerGetCurrentTemp);
40 |
41 | // Declare a Particle.function so that we can adjust the accelerometer threshold from the cloud.
42 | Particle.function("SetXYZThresh",AssetTrackerSetAccelThresh);
43 |
44 | // Declare a Particle.function so that we can query recent accelerometer data from the cloud.
45 | Particle.function("GetRecentXYZ",AssetTrackerGetRecentAccel);
46 |
47 |
48 | // Set the returned location handler function by the locationCallback() method
49 | // Initialize the Asset Tracker to check in once a Day 60*60*24
50 | locator.withSubscribe(AssetTrackerLocationCallback).withLocatePeriodic(86400);
51 |
52 | // Give this Electron a name so we can identify it
53 | // locator.withEventName("blockchain-iot-asset-tracker1");
54 | // locator.withLocatePeriodic(60);
55 |
56 | // LED pin configuration
57 | pinMode(ledonboard, OUTPUT);
58 |
59 | // Turn off LED on the Particle board when the application starts
60 | digitalWrite(ledonboard, LOW);
61 | }
62 |
63 |
64 | // Remotely change the accelerometer trigger threshold
65 | int AssetTrackerSetAccelThresh( String command ) {
66 | // Try to convert Srting to an integer
67 | int NewAccelThreshold = command.toInt();
68 | // Disgard any non-integer command strings sent from the cloud
69 | if ( NewAccelThreshold > 0) {
70 | AccelThreshold = NewAccelThreshold;
71 | Serial.print("Accelerometer Threshold now set to : ");
72 | Serial.println(command);
73 | return 1;
74 | }
75 | // Keep the predefined Threshold if function received garbage
76 | return 0;
77 | }
78 |
79 |
80 | int AssetTrackerSetReportInterval( String command ) {
81 | /* Particle.functions always take a string as an argument and return an integer.
82 | Since we can pass a string, it means that we can give the program commands on how the function should be used.
83 | In this case, telling the function a string that contains a Number will set the AssetTracker delay
84 | and telling it "off", 0 or some bogus command will turn the AssetTracker off.
85 | Then, the function returns a value to us to let us know what happened.
86 | In this case, it will return :
87 | New Delay value - when the Cellular Asset Tracker is turning on
88 | 0 when the Cellular Asset Tracker is turning off,
89 | */
90 | int Delay = command.toInt();
91 | if( Delay > 0 ) {
92 | locator.withSubscribe(AssetTrackerLocationCallback).withLocatePeriodic(Delay);
93 | digitalWrite(ledonboard,HIGH);
94 | Serial.print("Enabling Asset Location reporting interval:");
95 | Serial.println(command);
96 | return Delay;
97 | } else {
98 | // Any invalid string that doesn't convert to a number or 0 should be considered "Off"
99 | // "once a day" to be sufficiently large to be OFF
100 | locator.withSubscribe(AssetTrackerLocationCallback).withLocatePeriodic(86400);
101 | digitalWrite(ledonboard,LOW);
102 | Serial.println("Disabling Asset Location reporting");
103 | return 0;
104 | }
105 |
106 | }
107 |
108 |
109 | int AssetTrackerGetCurrentTemp(String Coordinates ) {
110 | byte i;
111 | byte present = 0;
112 | byte type_s;
113 | byte data[12];
114 | byte addr[8];
115 | float celsius, fahrenheit;
116 | int init = 0;
117 |
118 | // wait to initialize / find the chip
119 | while( init < 10 ) {
120 | if ( !ds.search(addr)) {
121 | Serial.println("Searching for Temperature Sensor...");
122 | ds.reset_search();
123 | delay(250);
124 | init++;
125 | } else {
126 | init = 10; // found
127 | }
128 | }
129 |
130 | // The order is changed a bit in this example
131 | // first the returned address is printed
132 | Serial.print("ROM =");
133 | for( i = 0; i < 8; i++) {
134 | Serial.write(' ');
135 | Serial.print(addr[i], HEX);
136 | }
137 |
138 | // second the CRC is checked, on fail,
139 | // print error and just return to try again
140 | if (OneWire::crc8(addr, 7) != addr[7]) {
141 | Serial.println("CRC is not valid!");
142 | return 0;
143 | }
144 | Serial.println();
145 |
146 | // we have a good address at this point
147 | // what kind of chip do we have?
148 | // we will set a type_s value for known types or just return
149 |
150 | // the first ROM byte indicates which chip
151 | switch (addr[0]) {
152 | case 0x10:
153 | Serial.println(" Chip = DS1820/DS18S20");
154 | type_s = 1;
155 | break;
156 | case 0x28:
157 | Serial.println(" Chip = DS18B20");
158 | type_s = 0;
159 | break;
160 | case 0x22:
161 | Serial.println(" Chip = DS1822");
162 | type_s = 0;
163 | break;
164 | case 0x26:
165 | Serial.println(" Chip = DS2438");
166 | type_s = 2;
167 | break;
168 | default:
169 | Serial.println("Unknown device type.");
170 | return 0;
171 | }
172 |
173 | // this device has temp so let's read it
174 | ds.reset(); // first clear the 1-wire bus
175 | ds.select(addr); // now select the device we just found
176 | // ds.write(0x44, 1); // tell it to start a conversion, with parasite power on at the end
177 | ds.write(0x44, 0); // or start conversion in powered mode (bus finishes low)
178 |
179 | // just wait a second while the conversion takes place
180 | // different chips have different conversion times, check the specs, 1 sec is worse case + 250ms
181 | // you could also communicate with other devices if you like but you would need
182 | // to already know their address to select them.
183 | delay(1000); // maybe 750ms is enough, maybe not, wait 1 sec for conversion
184 |
185 | // we might do a ds.depower() (parasite) here, but the reset will take care of it.
186 |
187 | // first make sure current values are in the scratch pad
188 | present = ds.reset();
189 | ds.select(addr);
190 | ds.write(0xB8,0); // Recall Memory 0
191 | ds.write(0x00,0); // Recall Memory 0
192 |
193 | // now read the scratch pad
194 | present = ds.reset();
195 | ds.select(addr);
196 | ds.write(0xBE,0); // Read Scratchpad
197 | if (type_s == 2) {
198 | ds.write(0x00,0); // The DS2438 needs a page# to read
199 | }
200 |
201 | // transfer and print the values
202 | Serial.print(" Data = ");
203 | Serial.print(present, HEX);
204 | Serial.print(" ");
205 | for ( i = 0; i < 9; i++) { // we need 9 bytes
206 | data[i] = ds.read();
207 | Serial.print(data[i], HEX);
208 | Serial.print(" ");
209 | }
210 | Serial.print(" CRC=");
211 | Serial.print(OneWire::crc8(data, 8), HEX);
212 | Serial.println();
213 |
214 | // Convert the data to actual temperature
215 | // because the result is a 16 bit signed integer, it should
216 | // be stored to an "int16_t" type, which is always 16 bits
217 | // even when compiled on a 32 bit processor.
218 | int16_t raw = (data[1] << 8) | data[0];
219 | if (type_s == 2) raw = (data[2] << 8) | data[1];
220 | byte cfg = (data[4] & 0x60);
221 |
222 | switch (type_s) {
223 | case 1:
224 | raw = raw << 3; // 9 bit resolution default
225 | if (data[7] == 0x10) {
226 | // "count remain" gives full 12 bit resolution
227 | raw = (raw & 0xFFF0) + 12 - data[6];
228 | }
229 | celsius = (float)raw * 0.0625;
230 | break;
231 | case 0:
232 | // at lower res, the low bits are undefined, so let's zero them
233 | if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms
234 | if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms
235 | if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms
236 | // default is 12 bit resolution, 750 ms conversion time
237 | celsius = (float)raw * 0.0625;
238 | break;
239 |
240 | case 2:
241 | data[1] = (data[1] >> 3) & 0x1f;
242 | if (data[2] > 127) {
243 | celsius = (float)data[2] - ((float)data[1] * .03125);
244 | } else {
245 | celsius = (float)data[2] + ((float)data[1] * .03125);
246 | }
247 | }
248 |
249 | // remove random errors
250 | if((((celsius <= 0 && celsius > -1) && lastTemp > 5)) || celsius > 125) {
251 | celsius = lastTemp;
252 | }
253 |
254 | fahrenheit = celsius * 1.8 + 32.0;
255 | lastTemp = celsius;
256 |
257 | // now that we have the readings, we can publish them to the cloud
258 | // store celsius and fahrenheit temp readings in "temperature" stringified JSON
259 | String temperature = String::format("{\"Celsius\":%f,\"Fahrenheit\":%f}", celsius, fahrenheit );
260 | String TempPlusLocation;
261 | if( Coordinates.length() != 0) {
262 | TempPlusLocation = String("{\"Temp\":"+temperature+",\"gps\":"+Coordinates+"}");
263 | } else {
264 | TempPlusLocation = String("{\"Temp\":"+temperature+"}"); // This was a web query, location unknown
265 | }
266 | Particle.publish("AssetTrackerTemperatureEvent", TempPlusLocation, PRIVATE); // publish to cloud
267 | Serial.print( "Sending AssetTrackerTemperatureEvent : " );
268 | Serial.println( TempPlusLocation );
269 | return (int)fahrenheit ;
270 | }
271 |
272 |
273 | int AssetTrackerGetRecentAccel( String Coordinates ) {
274 | // Check if there's been a big acceleration
275 | // Report the largest acceleration detected during the prior time interval
276 | if ( MaxAccelThisInterval ) {
277 | String AccelPlusLocation;
278 | if( Coordinates.length() != 0) {
279 | AccelPlusLocation = String("{\"Accel\":"+MaxAccelJSON+",\"gps\":"+Coordinates+"}");
280 | } else {
281 | AccelPlusLocation = String("{\"Accel\":"+MaxAccelJSON+"}"); // This was a web query, location unknown
282 | }
283 | Particle.publish("AssetTrackerAccelerationEvent", AccelPlusLocation, 60, PRIVATE);
284 | Serial.print( "Sending AssetTrackerAccelerationEvent : " );
285 | Serial.println( AccelPlusLocation );
286 | }
287 |
288 | // Report the Max Acceleration back to Particle Function return code
289 | // Reset the Max Acceleration for the next time interval to zero
290 | int reportMaxAccel = MaxAccelThisInterval;
291 | MaxAccelThisInterval = 0;
292 | return reportMaxAccel;
293 | }
294 |
295 |
296 | void AssetTrackerLocationCallback(float lat, float lon, float accuracy) {
297 | // Handle the returned location data for the device. This method is passed three arguments:
298 | // - Latitude
299 | // - Longitude
300 | // - Accuracy of estimated location (in meters)
301 | String Coordinates;
302 | Coordinates = String::format("{\"lat\":%f,\"lon\":%f,\"accuracy\":%d}", lat, lon, accuracy);
303 |
304 | // Check here if the Particle Asset Tracker v2 built-in GPS can get a more accurate geolocation
305 | // than the Cellular Tower Triangulation. Consumes more power but improves accuracy.
306 |
307 | // Report the temperture at this location.
308 | AssetTrackerGetCurrentTemp( Coordinates );
309 |
310 | // Determine if there has been a big acceleration event in the past interval
311 | AssetTrackerGetRecentAccel( Coordinates );
312 | }
313 |
314 |
315 | void loop() {
316 | locator.loop();
317 |
318 | // Check if there's been a big acceleration
319 | // Save only the largest acceleration detected during the prior time period
320 | int CurrentAccelmagnitude = t.readXYZmagnitude();
321 | if (CurrentAccelmagnitude > AccelThreshold && CurrentAccelmagnitude > MaxAccelThisInterval) {
322 | // Format a JSON Object to be parsed in the cloud {x:X,y:Y,z:Z}
323 | // Save a stringified JSON object
324 | MaxAccelJSON = String::format("{\"x\":%d,\"y\":%d,\"z\":%d}", t.readX(), t.readY(), t.readZ());
325 | Serial.print( "AccelerationEvent triggered: " );
326 | Serial.println( MaxAccelJSON );
327 | MaxAccelThisInterval = CurrentAccelmagnitude;
328 | }
329 | }
330 |
--------------------------------------------------------------------------------
/ParticleElectron/project.properties:
--------------------------------------------------------------------------------
1 | dependencies.Adafruit_LIS3DH=1.0.3
2 | dependencies.Adafruit_GPS=1.0.3
3 | dependencies.AssetTracker=0.0.10
4 | dependencies.CellularHelper=0.0.4
5 | dependencies.OneWire=2.0.1
6 | dependencies.Adafruit_Sensor=1.0.2
7 | dependencies.google-maps-device-locator=0.0.4
8 |
--------------------------------------------------------------------------------
/ParticleElectron/screenshots/ParticleConsoleDeviceEvents.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/ParticleElectron/screenshots/ParticleConsoleDeviceEvents.png
--------------------------------------------------------------------------------
/ParticleElectron/screenshots/ParticleElectronAssetTracker-IoT.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/ParticleElectron/screenshots/ParticleElectronAssetTracker-IoT.jpg
--------------------------------------------------------------------------------
/ParticleElectron/screenshots/ParticleElectronAssetTracker-Kit.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/ParticleElectron/screenshots/ParticleElectronAssetTracker-Kit.jpg
--------------------------------------------------------------------------------
/ParticleElectron/screenshots/ParticleElectronAssetTracker-in-Case.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/IBM/IoT-AssetTracking-Perishable-Network-Blockchain/75e46e90c43311b69f29def7243f6eef015f601d/ParticleElectron/screenshots/ParticleElectronAssetTracker-in-Case.jpg
--------------------------------------------------------------------------------
/README-ja.md:
--------------------------------------------------------------------------------
1 | *Read this in other languages: [English](README.md).*
2 |
3 | # Hyperledger ブロックチェーンを使用した IoT 資産追跡アプリの開発
4 |
5 | ## イントロダクション
6 |
7 | このリポジトリには **IoT資産追跡デバイス**、**Hyperledger ブロックチェーン**、**Node-RED ダッシュボード** を組み立てる3つのセクションがあり、生鮮品のネットワークサプライチェーンを実装します。
8 |
9 | 温度、湿度、振動、または時間に影響されやすい生鮮品 (食品サプライ・チェーン、冷却保管された医薬品、園芸植物など) の配送に関連する環境条件を追跡するには、このコード・パターンを使用できます。貨物を安全な環境パラメーターの範囲内で安全な時間内に配送しなければならないとしたら、環境センサーを結合した IoT 資産追跡デバイスを使用して、GPS、三角測量、またはビーコンによって現在位置を計算して、その位置をセルラー、5G、Sub1GHz、SigFox、または WiFi のネットワークを介して報告することには極めて大きな価値があります。安全な配送と貨物の決済に、農場、製造業者、処理工場、トラック、港湾、船、流通センター、消費者向け小売店などの複数の参加者が関与する場合、Hyperledger ブロックチェーンを使用すれば、IoT 資産追跡デバイスから報告される配送の進捗を、不変のトランザクションとして記録することができます。
10 |
11 | ## ワークショップ
12 |
13 | 私はこのgitリポジトリに関して **[IBM コードパターン](https://developer.ibm.com/jp/)** の [ワークショップ・チュートリアル](Workshop/README-ja.md) にまとめました。
14 | この手順に従って、自分でビルドする方法を学んでください!
15 |
16 | ## セクションの概要
17 |
18 | [最初のセクション](ParticleElectron/README-ja.md) は、**Particle Electron Asset Tracker v2** をセットアップして環境センサーのデータと場所をクラウドに送信する方法を詳しく説明しています。
19 | この実装では、[Particle Electron](https://docs.particle.io/datasheets/kits-and-accessories/particle-shields/#electron-asset-tracker-v2) を使用しますが、他の多くの IoT 資産追跡デバイスでも、場所とデータを送信できるものであれば、同様の結果を得ることができます。
20 | このワークショップチュートリアルのその後の改訂では、他の IoT 資産追跡ボードが追加される予定ですので、今後もチェックしてください。
21 |
22 | [2番目のセクション](Blockchain/README-ja.md) は、[Hyperledger](https://www.hyperledger.org/) Fabric、Hyperledger Composer、Hyperledger Composer REST APIを使用して、IBM Cloud 上の [Kubernetes cluster](https://console.bluemix.net/docs/tutorials/scalable-webapp-kubernetes.html#deploy-a-scalable-web-application-on-kubernetes) で管理された [IBM Cloud Container Service](https://www.ibm.com/cloud/container-service) 上で、**生鮮品のビジネスネットワーク** を実装しています。
23 |
24 | [3番目のセクション](Node-RED/README-ja.md) では、**Where、What、When** のパワーが、ジオロケーションパスや環境センサーデータをプロットするダッシュボードで最もよく視覚化され、トリガーとアラートを制御できることを示します。
25 | IBM Cloud でホストされた Cloud Foundry アプリケーションで稼働する **[Node-RED](https://nodered.org/)** と Node.js サーバーを使用し、IoT 資産追跡データを受信して、Hyperledger Composer REST API 経由で Hyperledgerファブリックに書き込みます。
26 | また、**Node-RED ダッシュボード** を使用して地図上に貨物をプロットします。
27 |
28 | 楽しくやりましょう!
29 | このチュートリアルを改善する提案がある場合は、私にフィードバックしてください。
30 |
31 | # ライセンス
32 |
33 | [Apache 2.0](LICENSE)
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | *Read this in other languages: [日本語](README-ja.md).*
2 |
3 | # IoT Asset Tracking using a Hyperledger Blockchain
4 |
5 | # WARNING: This repository is no longer maintained :warning:
6 |
7 | > This repository, which contains assets to run a Hyperledger Composer application,
8 | is not being actively maintained due to a shift to focus on Hyperledger Fabric.
9 | This repository will not be updated. The repository will be kept available
10 | in read-only mode. Refer to https://github.com/IBM/assetTracking
11 | for a similar example.
12 |
13 | ## Introduction
14 | This repository contains three sections which assemble an **IoT Asset Tracking device**, **Hyperledger Blockchain** and a **Node-RED Dashboard** to implement a perishable network supply chain. This example can be used to track environmental conditions for a food safety supply chain, refrigerated medical supplies, garden plant shipments or any perishable shipment that are temperature / humidity / vibration / time sensitive. If a cargo needs to be delivered within safe environmental parameters and time, the use of an IoT Asset Tracking device that combines environmental sensors, calculates its location via GPS, triangulation or beacons, and then reports its location via Cellular, 5G, Sub1GHz, SigFox, WiFi networks is extremely valuable. When multiple participants - farms, manufacturers, processing plants, trucks, ports, ships, distribution centers, consumer retail outlets - are involved in the safe shipment and payment of the cargo, a Hyperledger Blockchain can be used to record immutable transactions as the cargo shipment progresses through its delivery journey.
15 |
16 | ## Workshop
17 | I've arranged this git repository to be read as an **[IBM Code Pattern](https://developer.ibm.com/code/)** [workshop tutorial](Workshop/README.md). Follow the steps in the [Workshop directory](Workshop/README.md) to learn how to build one yourself!
18 |
19 | ## Section Overviews
20 | The first [section](ParticleElectron/README.md) details how to set up a **Particle Electron Asset Tracker v2** to send environmental sensor data and location to the cloud. This implementation uses a [Particle Electron](https://docs.particle.io/datasheets/kits-and-accessories/particle-shields/#electron-asset-tracker-v2) but many other IoT Asset Tracking devices that can transmit location and data can be substituted with similar results. Subsequent revisions of this workshop tutorial will add other IoT Asset Tracking boards so check back in the future.
21 |
22 | The second [section](Blockchain/README.md) implements a **Perishable Business Network** using [Hyperledger](https://www.hyperledger.org/) Fabric, Hyperledger Composer, Hyperledger Composer REST APIs running in the [IBM Cloud Container Service](https://www.ibm.com/cloud/container-service) managed by a [Kubernetes cluster](https://console.bluemix.net/docs/tutorials/scalable-webapp-kubernetes.html#deploy-a-scalable-web-application-on-kubernetes) in the IBM Cloud.
23 |
24 | In the third [section](Node-RED/README.md), the power of **Where, What and When** is best visualized in a dashboard that plots the geo location path, the environmental sensor data and can control triggers and alerts. I use **[Node-RED](https://nodered.org/)** and a Node.js server running in an IBM Cloud hosted Cloud Foundry application to receive the IoT Asset Tracking data and write it to the Hyperledger Fabric using Hyperledger Composer REST APIs. I also use a **Node-RED Dashboard** to plot the shipment on a map.
25 |
26 | Enjoy! Give me feedback if you have suggestions on how to improve this tutorial.
27 |
28 | ## License
29 | This code pattern is licensed under the Apache Software License, Version 2. Separate third party code objects invoked within this code pattern are licensed by their respective providers pursuant to their own separate licenses. Contributions are subject to the [Developer Certificate of Origin, Version 1.1 (DCO)](https://developercertificate.org/) and the [Apache Software License, Version 2](http://www.apache.org/licenses/LICENSE-2.0.txt).
30 |
31 | [Apache Software License (ASL) FAQ](http://www.apache.org/foundation/license-faq.html#WhatDoesItMEAN)
32 |
--------------------------------------------------------------------------------
/Workshop/README-ja.md:
--------------------------------------------------------------------------------
1 | *Read this in other languages: [English](README.md).*
2 |
3 | # IoT 資産トラッカー Perishable Network ブロックチェーン ワークショップ
4 | 著者: [@johnwalicki](https://twitter.com/johnwalicki)
5 |
6 | # 元となるワークショップは: **https://github.com/johnwalicki/IoT-AssetTracking-Perishable-Network-Blockchain**
7 |
8 | 私はこのgitリポジトリを **[IBM コードパターン](https://developer.ibm.com/code/)** の [ワークショップ・チュートリアル](README-ja.md) として読むように調整しました。
9 |
10 | ## セクションの概要
11 |
12 | [最初のセクション](../ParticleElectron/README-ja.md) は、**Particle Electron Asset Tracker v2** をセットアップして環境センサーのデータと場所をクラウドに送信する方法を詳しく説明しています。
13 | 我々は多数の Particle Electrons を持たないので、私はその代表として所持するものをデモします。ワークショップの最後に、このトラッカーから環境データを読んでいきます。
14 |
15 | [2番目のセクション](../Blockchain/README-ja.md) は、[Hyperledger](https://www.hyperledger.org/) Fabric、Hyperledger Composer、Hyperledger Composer REST APIを使用して、IBM Cloud 上の [Kubernetes cluster](https://console.bluemix.net/docs/tutorials/scalable-webapp-kubernetes.html#deploy-a-scalable-web-application-on-kubernetes) で管理された [IBM Cloud Container Service](https://www.ibm.com/cloud/container-service) 上で、**生鮮品のビジネスネットワーク** を実装しています。
16 |
17 | [3番目のセクション](../Node-RED/README-ja.md) では、**Where、What、When** のパワーが、ジオロケーションパスや環境センサーデータをプロットするダッシュボードで最もよく視覚化され、トリガーとアラートを制御できることを示します。
18 | IBM Cloud でホストされた Cloud Foundry アプリケーションで稼働する **[Node-RED](https://nodered.org/)** と Node.js サーバーを使用し、IoT 資産追跡データを受信して、Hyperledger Composer REST API 経由で Hyperledgerファブリックに書き込みます。
19 | また、**Node-RED ダッシュボード** を使用して地図上に貨物をプロットします。
20 |
21 | * 独自の Particle Electron を購入した場合は、Particle のデバイスIDとアクセストークンを知り、それを Node-RED 初期化フローに設定する必要があります。
22 | * あなたがワークショップに参加している場合、インストラクターは Particle のデバイスIDとアクセストークンを別のスライド (GitHubには含まれません) で共有します。
23 |
24 | ワークショップの最後には、食品安全サプライチェーンが導入された Hyperledger ブロックチェーンと、Particle のルートを追跡する Node-RED Map ダッシュボードが用意されています。
25 |
--------------------------------------------------------------------------------
/Workshop/README.md:
--------------------------------------------------------------------------------
1 | *Read this in other languages: [日本語](README-ja.md).*
2 |
3 | # IoT Asset Tracking Perishable Network Blockchain Workshop
4 | Author: [@johnwalicki](https://twitter.com/johnwalicki)
5 |
6 | # Follow this workshop at **https://github.com/johnwalicki/IoT-AssetTracking-Perishable-Network-Blockchain**
7 |
8 | I've arranged this git repository to be read as an **[IBM Code Pattern](https://developer.ibm.com/code/)** [workshop tutorial](README.md).
9 |
10 | ## Section Overviews
11 | The first [section](../ParticleElectron/README.md) details how to set up a **Particle Electron Asset Tracker v2** to send environmental sensor data and location to the cloud. This implementation uses a [Particle Electron](https://docs.particle.io/datasheets/kits-and-accessories/particle-shields/#electron-asset-tracker-v2). Since we don't have dozens of Particle Electrons, I will demo mine from the podium. By the end of the workshop you will be reading environmental data off this tracker.
12 |
13 | The second [section](../Blockchain/README.md) implements a **Perishable Business Network** using [Hyperledger](https://www.hyperledger.org/) Fabric, Hyperledger Composer, Hyperledger Composer REST APIs running in the [IBM Cloud Container Service](https://www.ibm.com/cloud/container-service) managed by a [Kubernetes cluster](https://console.bluemix.net/docs/tutorials/scalable-webapp-kubernetes.html#deploy-a-scalable-web-application-on-kubernetes) in the IBM Cloud.
14 |
15 | In the third [section](../Node-RED/README.md), the power of **Where, What and When** is best visualized in a dashboard that plots the geo location path, the environmental sensor data and can control triggers and alerts. I use **[Node-RED](https://nodered.org/)** running in the IBM Cloud to receive the IoT Asset Tracking data and write it to the Hyperledger Fabric using Hyperledger Composer REST APIs. I also use a **Node-RED Dashboard** to plot the shipment on a map.
16 |
17 | * If you purchased your own Particle Electron, you will need to know the Particle Device ID and Access Token and insert it into Node-RED initialization flow.
18 | * If your participating in a workshop, the instructor will share the Particle Device ID and Access Token in a separate slide (not part of GitHub)
19 |
20 | At the end of the workshop, you will have a complete Hyperledger Blockchain with a food safety supply chain implemented and a Node-RED Map Dashboard that tracks the routes of my Particle.
21 |
--------------------------------------------------------------------------------