2
2
* NetSwarm library
3
3
*
4
4
*
5
+ * Note that this implementation uses templates, which means it can't be
6
+ * compiled as a regular C++ file; it is included in the header instead.
7
+ * http://stackoverflow.com/q/495021/2866660
8
+ *
5
9
* Created 05 Aug 2016
6
10
* by wvengen
7
- * Modified 22 Aug 2016
11
+ * Modified 12 Sep 2016
8
12
* by wvengen
9
13
*
10
14
* https://github.com/wvengen/netswarm-arduino/blob/master/NetSwarm.cpp
23
27
* Public methods
24
28
*/
25
29
26
- NetSwarm::NetSwarm (byte dataVersion, unsigned int eepromOffset) {
30
+ template <class ModbusT >
31
+ NetSwarm<ModbusT>::NetSwarm(byte dataVersion, unsigned int eepromOffset) {
27
32
#ifdef USE_NETSWARM_EEPROM
28
33
this ->dataVersion = dataVersion;
29
34
this ->eepromOffset = eepromOffset;
30
35
#endif
31
36
this ->setupDone = false ;
32
- this ->mb = new NETSWARM_MODBUS_CLASS ();
33
37
}
34
38
35
- void NetSwarm::config () {
39
+ template <class ModbusT >
40
+ void NetSwarm<ModbusT>::config() {
36
41
#ifdef USE_NETSWARM_EEPROM
37
42
setupEeprom ();
38
43
#endif
@@ -41,33 +46,36 @@ void NetSwarm::config() {
41
46
setupDone = true ;
42
47
}
43
48
44
- void NetSwarm::setCommandCallback (command_callback_t callback) {
49
+ template <class ModbusT >
50
+ void NetSwarm<ModbusT>::setCommandCallback(command_callback_t callback) {
45
51
commandCallback = callback;
46
52
}
47
53
48
- void NetSwarm::task () {
49
- mb->task ();
50
- if (Coil (COIL_APPLY)) {
54
+ template <class ModbusT >
55
+ void NetSwarm<ModbusT>::task() {
56
+ ModbusT::task ();
57
+ if (ModbusT::Coil (COIL_APPLY)) {
51
58
setupNetwork ();
52
- Coil (COIL_APPLY, 0 );
59
+ ModbusT:: Coil (COIL_APPLY, 0 );
53
60
if (commandCallback) commandCallback (COIL_APPLY);
54
61
}
55
62
#ifdef USE_NETSWARM_EEPROM
56
- if (Coil (COIL_SAVE)) {
63
+ if (ModbusT:: Coil (COIL_SAVE)) {
57
64
saveEeprom ();
58
- Coil (COIL_SAVE, 0 );
65
+ ModbusT:: Coil (COIL_SAVE, 0 );
59
66
if (commandCallback) commandCallback (COIL_SAVE);
60
67
}
61
- if (Coil (COIL_LOAD)) {
68
+ if (ModbusT:: Coil (COIL_LOAD)) {
62
69
loadEeprom ();
63
- Coil (COIL_LOAD, 0 );
70
+ ModbusT:: Coil (COIL_LOAD, 0 );
64
71
if (commandCallback) commandCallback (COIL_LOAD);
65
72
}
66
73
#endif
67
74
}
68
75
69
76
#ifdef USE_NETSWARM_EEPROM
70
- bool NetSwarm::loadEeprom () {
77
+ template <class ModbusT >
78
+ bool NetSwarm<ModbusT>::loadEeprom() {
71
79
// make sure we have valid data in the EEPROM
72
80
setupEeprom ();
73
81
if (currentDataVersion == 0 || dataVersion != currentDataVersion) {
@@ -81,13 +89,14 @@ bool NetSwarm::loadEeprom() {
81
89
do {
82
90
w = (EEPROM.read (eepromOffset + 4 + reg->offset * 2 + 0 ) << 8 ) +
83
91
(EEPROM.read (eepromOffset + 4 + reg->offset * 2 + 1 ));
84
- mb-> Hreg (reg->offset , w);
92
+ ModbusT:: Hreg (reg->offset , w);
85
93
reg = reg->next ;
86
94
} while (reg);
87
95
return true ;
88
96
}
89
97
90
- void NetSwarm::saveEeprom () {
98
+ template <class ModbusT >
99
+ void NetSwarm<ModbusT>::saveEeprom() {
91
100
// write header
92
101
EEPROM.write (eepromOffset + 0 , (byte)' N' );
93
102
EEPROM.write (eepromOffset + 1 , (byte)' S' );
@@ -99,20 +108,22 @@ void NetSwarm::saveEeprom() {
99
108
if (reg == 0 ) return ;
100
109
word w;
101
110
do {
102
- w = mb-> Hreg (reg->offset );
111
+ w = ModbusT:: Hreg (reg->offset );
103
112
EEPROM.write (eepromOffset + 4 + reg->offset * 2 + 0 , (byte)(w >> 8 ));
104
113
EEPROM.write (eepromOffset + 4 + reg->offset * 2 + 1 , (byte)(w & 0xff ));
105
114
reg = reg->next ;
106
115
} while (reg);
107
116
}
108
117
#endif /* USE_NETSWARM_EEPROM */
109
118
110
- byte NetSwarm::getId () {
119
+ template <class ModbusT >
120
+ byte NetSwarm<ModbusT>::getId() {
111
121
word v = HregRead (HREG_IP_ADDR_2, HREG_IP_ADDR_DEFAULT_2) & 0xff ;
112
122
return v - NETSWARM_IP_START_4;
113
123
}
114
124
115
- void NetSwarm::getIpAddr (byte ip[4 ]) {
125
+ template <class ModbusT >
126
+ void NetSwarm<ModbusT>::getIpAddr(byte ip[4 ]) {
116
127
word value;
117
128
118
129
value = HregRead (HREG_IP_ADDR_1, HREG_IP_ADDR_DEFAULT_1);
@@ -123,18 +134,21 @@ void NetSwarm::getIpAddr(byte ip[4]) {
123
134
ip[3 ] = value & 0xff ;
124
135
}
125
136
126
- void NetSwarm::getIpBcast (byte ip[4 ]) {
137
+ template <class ModbusT >
138
+ void NetSwarm<ModbusT>::getIpBcast(byte ip[4 ]) {
127
139
getIpAddr (ip);
128
140
ip[3 ] = 0xff ; // @todo configurable netmask
129
141
}
130
142
131
- void NetSwarm::getMacAddr (byte mac[6 ]) {
143
+ template <class ModbusT >
144
+ void NetSwarm<ModbusT>::getMacAddr(byte mac[6 ]) {
132
145
mac[0 ] = 2 ; // locally administered mac range, unicast
133
146
getIpAddr (&mac[2 ]);
134
147
}
135
148
136
149
#ifdef USE_NETSWARM_MASTER
137
- void NetSwarm::sendHreg (IPAddress ip, word offset, word value) {
150
+ template <class ModbusT >
151
+ void NetSwarm<ModbusT>::sendHreg(IPAddress ip, word offset, word value) {
138
152
// use separate buffers to avoid trouble when packet in coming in
139
153
byte sendbuffer[7 + 5 ]; // MBAP + frame
140
154
byte *MBAP = &sendbuffer[0 ];
@@ -181,11 +195,12 @@ void NetSwarm::sendHreg(IPAddress ip, word offset, word value) {
181
195
*/
182
196
183
197
// Read Modbus holding register with fallback to EEPROM and given value
184
- word NetSwarm::HregRead (word offset, word fallback) {
198
+ template <class ModbusT >
199
+ word NetSwarm<ModbusT>::HregRead(word offset, word fallback) {
185
200
// if Modbus was fully setup, use memory registers
186
201
// enables e.g. applying network settings without saving in EEPROM
187
202
if (setupDone) {
188
- return Hreg (offset);
203
+ return ModbusT:: Hreg (offset);
189
204
190
205
#ifdef USE_NETSWARM_EEPROM
191
206
// if we have valid data in the EEPROM, use that
@@ -201,14 +216,15 @@ word NetSwarm::HregRead(word offset, word fallback) {
201
216
}
202
217
}
203
218
204
- void NetSwarm::setupNetwork () {
219
+ template <class ModbusT >
220
+ void NetSwarm<ModbusT>::setupNetwork () {
205
221
byte ip[4 ];
206
222
byte mac[6 ];
207
223
208
224
getIpAddr (ip);
209
225
getMacAddr (mac);
210
226
211
- mb-> config (mac, ip);
227
+ ModbusT:: config (mac, ip);
212
228
#ifdef USE_NETSWARM_MASTER
213
229
#ifdef USE_NETSWARM_MODBUS_IP
214
230
// nothing to do
@@ -220,20 +236,22 @@ void NetSwarm::setupNetwork() {
220
236
}
221
237
222
238
// Setup default modbus registers
223
- void NetSwarm::setupRegisters () {
239
+ template <class ModbusT >
240
+ void NetSwarm<ModbusT>::setupRegisters () {
224
241
// the ip-addresses are expected to be persistant and at the start
225
242
addHregPersist (HREG_IP_ADDR_1, HregRead (HREG_IP_ADDR_1, HREG_IP_ADDR_DEFAULT_1));
226
243
addHregPersist (HREG_IP_ADDR_2, HregRead (HREG_IP_ADDR_2, HREG_IP_ADDR_DEFAULT_2));
227
244
228
- addCoil (COIL_APPLY);
245
+ ModbusT:: addCoil (COIL_APPLY);
229
246
#ifdef USE_NETSWARM_EEPROM
230
- addCoil (COIL_SAVE);
231
- addCoil (COIL_LOAD);
247
+ ModbusT:: addCoil (COIL_SAVE);
248
+ ModbusT:: addCoil (COIL_LOAD);
232
249
#endif
233
250
}
234
251
235
252
#ifdef USE_NETSWARM_EEPROM
236
- void NetSwarm::setupEeprom () {
253
+ template <class ModbusT >
254
+ void NetSwarm<ModbusT>::setupEeprom () {
237
255
// first make sure we have the magic 'NSd' at the beginning
238
256
if (EEPROM.read (eepromOffset + 0 ) == (byte)' N' &&
239
257
EEPROM.read (eepromOffset + 1 ) == (byte)' S' &&
@@ -245,7 +263,8 @@ void NetSwarm::setupEeprom() {
245
263
}
246
264
}
247
265
248
- void NetSwarm::setPersist (word offset) {
266
+ template <class ModbusT >
267
+ void NetSwarm<ModbusT>::setPersist (word offset) {
249
268
// (based on Modbus::addReg implementation)
250
269
TPRegister *reg;
251
270
reg = (TPRegister*) malloc (sizeof (TPRegister));
0 commit comments