forked from Azure/azure-iot-sdk-node
-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathsimple_sample_device_twin.js
199 lines (180 loc) · 7.52 KB
/
simple_sample_device_twin.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
'use strict';
var Client = require('azure-iot-device').Client;
//var Protocol = require('azure-iot-device-amqp').Amqp;
var Protocol = require('azure-iot-device-mqtt').Mqtt;
var _ = require('lodash');
var connectionString = process.argv[2];
// create the IoTHub client
var client = Client.fromConnectionString(connectionString, Protocol);
console.log('got client');
// connect to the hub
client.open(function(err) {
if (err) {
console.error('could not open IotHub client');
} else {
console.log('client opened');
// Create device Twin
client.getTwin(function(err, twin) {
if (err) {
console.error('could not get twin');
} else {
console.log('twin created');
// First, set up code to handle desired property changes.
// Important note: when the twin is done being created, the desired
// properties have already been retrieved from the service. When we
// add these handlers, there is a chance that the handlers will be called
// almost immediately if the relevant properties have already been
// retrieved from the service. In this way "property change" could mean
// "the property is changing from one value to another value", or it could
// mean "the property is changing from being unset to being set."
//
// There are 4 examples here. The app developer has the option to chose
// which sample style to use (or mix and match). All of the events
// shown here will fire and it's up to the app developer to decide what
// to listen for.
//
// If there is a collision between different handlers, it is up to the
// app developer to resolve the collisions. In other words, there is
// nothing that stops the developer from writing two different handlers
// that process the same properties at different levels.
//
// Usage example #1: receiving all patches with a single event handler.
//
// This code will output any properties that are received from the
// service.
//
twin.on('properties.desired', function(delta) {
console.log('new desired properties received:');
console.log(JSON.stringify(delta));
});
// Usage example #2: receiving an event if anything under
// properties.desired.climate changes
//
// This code will output desired min and max temperature every time
// the service updates either one.
//
// For example (service API code):
// twin.properties.desired.update({
// climate : {
// minTemperature: 68,
// maxTemperature: 76
// }
// });
//
twin.on('properties.desired.climate', function(delta) {
//
// Notice that twin.properties.desired has already been updated before
// this function was called.
//
// If the delta contains a minTemp or a maxTemp, then update the
// hardware with the values stored in the twin. The twin has all the
// same values as the delta, but the delta only has values that
// have changed. When we need the "current values", we don't use the
// values stored in the delta because it's possible that the delta has
// one or the other, but not both.
//
if (delta.minTemperature || delta.maxTemperature) {
console.log('updating desired temp:');
console.log('min temp = ' + twin.properties.desired.climate.minTemperature);
console.log('max temp = ' + twin.properties.desired.climate.maxTemperature);
}
});
// Usage example #3: receiving an event for a single (scalar) property
// value. This event is only fired if the fanOn boolean value is part
// of the patch.
//
// This code will output the new desired fan state whenever the service
// updates it.
//
// For example (service API code):
// twin.properties.desired.update({
// climate : {
// hvac : {
// systemControl : {
// fanOn : true
// }
// }
// }
// });
twin.on('properties.desired.climate.hvac.sytemControl', function(fanOn) {
console.log('setting fan state to ' + fanOn);
});
// Usage example #4: handle add or delete operations. The app developer
// is responsible for inferring add/update/delete operations based on
// the contents of the patch.
//
// This code will output the results of adding, updating, or deleting
// modules.
//
// Add example (service API code):
// twin.properties.desired.update({
// modules : {
// wifi : { channel = 6, ssid = 'my_network' },
// climate : { id = 17, units = 'farenheit' }
// }
// });
//
// Update example (service API code):
// twin.properties.desired.update({
// modules : {
// wifi : { channel = 7, encryption = 'wpa', passphrase = 'foo' }
// }
// });
//
// Delete example (service API code):
// twin.properties.desired.update({
// modules : {
// climate = null
// }
// });
//
// To do this, first we have to keep track of "all modules that we know
// about".
var moduleList = {};
// Then we use this internal list and compare it to the delta to know
// if anything was added, removed, or updated.
twin.on('properties.desired.modules', function(delta) {
Object.keys(delta).forEach(function(key) {
if (delta[key] === null && moduleList[key]) {
// If our patch contains a null value, but we have a record of
// this module, then this is a delete operation.
console.log('deleting module ' + key);
delete moduleList[key];
} else if (delta[key]) {
if (moduleList[key]) {
// Our patch contains a module, and we've seen this before.
// Must be an update operation.
console.log('updating module ' + key + ':');
console.log(JSON.stringify(delta[key]));
// Store the complete object instead of just the delta
moduleList[key] = twin.properties.desired.modules[key];
} else {
// Our patch contains a module, but we've never seen this
// before. Must be an add operation.
console.log('adding module ' + key + ':');
console.log(JSON.stringify(delta[key]));
// Store the complete object instead of just the delta
moduleList[key] = twin.properties.desired.modules[key];
}
}
});
});
// create a patch to send to the hub
var patch = {
firmwareVersion:'1.2.1',
weather:{
temperature: 72,
humidity: 17
}
};
// send the patch
twin.properties.reported.update(patch, function(err) {
if (err) throw err;
console.log('twin state reported');
});
}
});
}
});