6 #ifndef __MULTICHANNELDEVICE_H__
7 #define __MULTICHANNELDEVICE_H__
21 extern void(* resetFunc) (void);
27 template <
class HalType,
class ChannelType,
int ChannelCount,
class List0Type=List0>
31 ChannelType* devchannels[ChannelCount];
43 void registerChannel(ChannelType& ch,uint8_t num) {
44 if( num >= 1 && num <= ChannelCount) {
45 devchannels[num-1] = &ch;
49 void layoutChannels () {
50 uint16_t addr = list0.address() + list0.size();
51 for( uint8_t i=0; i<this->channels(); ++i ) {
52 devchannels[i]->setup(
this,i+1,addr);
53 addr += devchannels[i]->size();
57 void channels (uint8_t num) {
58 DeviceType::channels(min(num,(uint8_t)ChannelCount));
61 uint8_t channels ()
const {
62 return DeviceType::channels();
66 DPRINT(F(
"Address Space: "));DDEC(this->keystore().address());DPRINT(F(
" - "));DDECLN(getUserStorage().getAddress());
71 ChannelType& ch = channel(this->channels());
75 uint16_t checksum () {
79 crc = HalType::crc16(crc,DeviceType::keystore().size());
81 for( uint8_t i=0; i<list0.size(); ++i ) {
82 crc = HalType::crc16(crc,list0.getRegister(i));
85 for( uint8_t c=1; c<=this->channels(); ++c ) {
86 ChannelType& ch = channel(c);
89 for( uint8_t i=0; i<l.getSize(); ++i ) {
90 crc = HalType::crc16(crc,l.getRegister(i));
94 for( uint8_t i=0; i<l.getSize(); ++i ) {
95 crc = HalType::crc16(crc,l.getRegister(i));
99 for( uint8_t i=0; i<l.getSize(); ++i ) {
100 crc = HalType::crc16(crc,l.getRegister(i));
103 crc = HalType::crc16(crc,ch.peers());
109 List0Type& getList0 () {
113 bool init (HalType& hal) {
117 bool first = storage().setup(checksum());
118 if( first ==
true ) {
122 this->keystore().init();
125 this->getDeviceID(
id);
127 hal.config(this->getConfigArea());
133 this->configChanged();
134 for( uint8_t cdx=1; cdx<=channels(); ++cdx ) {
135 channel(cdx).configChanged();
142 this->keystore().defaults();
144 for( uint8_t i=0; i<this->channels(); ++i ) {
145 devchannels[i]->firstinit();
150 if( getList0().localResetDisable() ==
false ) {
151 DPRINTLN(F(
"RESET"));
156 #elif ARDUINO_ARCH_STM32F1
163 DPRINTLN(F(
"BOOTLOADER"));
165 wdt_enable(WDTO_250MS);
170 void startPairing () {
171 this->sendDeviceInfo();
172 this->led().set(LedStates::pairing);
173 this->activity().stayAwake( seconds2ticks(20) );
176 ChannelType& channel(uint8_t ch) {
177 return *devchannels[ch-1];
181 bool worked = DeviceType::pollRadio();
182 for( uint8_t i=1; i<=this->channels(); ++i ) {
183 ChannelType& ch = channel(i);
184 if( ch.changed() ==
true ) {
185 this->sendInfoActuatorStatus(this->getMasterID(),this->nextcount(),ch);
193 if( getList0().aesActive() ==
true ) {
196 for( uint8_t i=1; i<=this->channels(); ++i) {
197 if( channel(i).aesActive() == true ) {
204 bool validSignature(
Message& msg) {
206 if( aesActive() ==
true ) {
207 return this->requestSignature(msg);
213 bool validSignature(uint8_t ch,
Message& msg) {
215 if( (ch==0 && aesActive()) || (this->hasChannel(ch)==
true && channel(ch).aesActive()==
true) ) {
216 return this->requestSignature(msg);
223 uint8_t answer = REPLAY_NO;
226 this->getDeviceID(devid);
227 if( msg.to() == devid || this->isBroadcastMsg(msg) ) {
229 this->radio().setSendTimeout();
233 if( this->isRepeat(msg) ==
true ) {
237 uint8_t mtype = msg.type();
238 uint8_t mcomm = msg.command();
239 uint8_t msubc = msg.subcommand();
240 if( mtype == AS_MESSAGE_CONFIG ) {
242 if( msubc == AS_CONFIG_PAIR_SERIAL && this->isDeviceSerial(msg.data())==
true ) {
243 this->led().set(LedStates::pairing);
244 this->activity().stayAwake( seconds2ticks(20) );
245 this->sendDeviceInfo(msg.from(),msg.length());
248 else if ( msubc == AS_CONFIG_PEER_ADD ) {
250 bool success =
false;
251 if( this->hasChannel(pm.channel()) ==
true ) {
252 if( validSignature(pm.channel(),msg) ==
true ) {
253 ch = &channel(pm.channel());
254 if( pm.peers() == 1 ) {
255 success = ch->peer(pm.peer1());
258 success = ch->peer(pm.peer1(),pm.peer2());
262 if( success ==
true ) {
268 answer = REPLAY_NACK;
272 else if ( msubc == AS_CONFIG_PEER_REMOVE ) {
274 bool success =
false;
275 if( this->hasChannel(pm.channel()) ==
true ) {
276 if( validSignature(pm.channel(),msg) ==
true ) {
277 ch = &channel(pm.channel());
278 success = ch->deletepeer(pm.peer1());
279 if( pm.peers() == 2 ) {
280 success &= ch->deletepeer(pm.peer2());
284 if( success ==
true ) {
290 answer = REPLAY_NACK;
294 else if( msubc == AS_CONFIG_PEER_LIST_REQ ) {
296 if( this->hasChannel(pm.channel()) ==
true ) {
297 this->sendInfoPeerList(msg.from(),msg.count(),channel(pm.channel()));
301 else if (msubc == AS_CONFIG_PARAM_REQ ) {
303 GenericList gl = findList(pm.channel(),pm.peer(),pm.list());
304 if( gl.valid() ==
true ) {
305 this->sendInfoParamResponsePairs(msg.from(),msg.count(),gl);
308 answer = REPLAY_NACK;
312 else if (msubc == AS_CONFIG_STATUS_REQUEST ) {
314 this->sendInfoActuatorStatus(msg.from(),msg.count(),channel(msg.command()),
false);
317 else if( msubc == AS_CONFIG_START ) {
319 if( validSignature(pm.channel(),msg) ==
true ) {
320 cfgChannel = pm.channel();
321 cfgList = findList(cfgChannel,pm.peer(),pm.list());
326 answer = REPLAY_NACK;
330 else if( msubc == AS_CONFIG_END ) {
331 if( cfgList.address() == list0.address() ) {
332 this->led().set(LedStates::nothing);
333 this->configChanged();
337 channel(cfgChannel).configChanged();
342 this->sendAck(msg,Message::WKMEUP);
344 else if( msubc == AS_CONFIG_WRITE_INDEX ) {
346 if( validSignature(pm.channel(),msg)==
true ) {
347 if( cfgChannel == pm.channel() && cfgList.valid() ==
true ) {
348 this->writeList(cfgList,pm.data(),pm.datasize());
353 answer = REPLAY_NACK;
356 else if( msubc == AS_CONFIG_SERIAL_REQ ) {
357 this->sendSerialInfo(msg.from(),msg.count());
360 answer = REPLAY_NACK;
363 else if( mtype == AS_MESSAGE_ACTION ) {
364 if ( mcomm == AS_ACTION_RESET || mcomm == AS_ACTION_ENTER_BOOTLOADER ) {
365 if( validSignature(msg) ==
true ) {
367 if( mcomm == AS_ACTION_ENTER_BOOTLOADER ) {
378 if( this->hasChannel(pm.channel())==
true ) {
379 ch = &channel(pm.channel());
380 if( validSignature(pm.channel(),msg)==
true ) {
382 case AS_ACTION_INHIBIT_OFF:
386 case AS_ACTION_INHIBIT_ON:
390 case AS_ACTION_STOP_CHANGE:
395 if( ch->inhibit() ==
false ) {
396 answer = ch->process(msg.actionSet()) ? REPLAY_ACK : REPLAY_NACK;
399 case AS_ACTION_COMMAND:
400 if( ch->inhibit() ==
false ) {
401 answer = ch->process(msg.actionCommand()) ? REPLAY_ACK : REPLAY_NACK;
410 else if( mtype == AS_MESSAGE_HAVE_DATA ) {
411 DPRINTLN(F(
"HAVE DATA"));
415 else if (mtype == AS_MESSAGE_REMOTE_EVENT || mtype == AS_MESSAGE_SENSOR_EVENT) {
416 answer = REPLAY_NACK;
418 uint8_t processed = 0;
419 for( uint8_t cdx=1; cdx<=this->channels(); ++cdx ) {
420 ChannelType* c = &channel(cdx);
421 if( c->inhibit() ==
false && c->has(pm.peer()) ==
true ) {
422 if( processed > 0 || validSignature(cdx,msg) ==
true ) {
426 case AS_MESSAGE_REMOTE_EVENT:
429 case AS_MESSAGE_SENSOR_EVENT:
430 ch->process(msg.sensorEvent());
437 if( processed > 1 ) {
445 else if (mtype == AS_MESSAGE_KEY_EXCHANGE ) {
446 if( validSignature(msg) ==
true ) {
447 if( this->keystore().exchange(msg.aesExchange())==
true ) answer = REPLAY_ACK;
448 else answer = REPLAY_NACK;
454 answer = REPLAY_NACK;
458 DPRINT(F(
"ignore "));
463 if( msg.ackRequired() ==
true && msg.to() == devid ) {
464 if( answer == REPLAY_ACK ) {
465 if( ch != 0 ) this->sendAck(msg, *ch);
466 else this->sendAck(msg);
468 else if( answer == REPLAY_NACK ) {
473 this->activity().stayAwake(millis2ticks(500));
480 }
else if (this->hasChannel(ch) ==
true) {
481 ChannelType& c = channel(ch);
484 }
else if (numlist == 2) {
486 }
else if (c.hasList3() && numlist == 3) {
487 return c.getList3(peer);
488 }
else if (c.hasList4() && numlist == 4) {
489 return c.getList4(peer);
495 void sendPeerEvent (
Message& msg,
const ChannelType& ch) {
497 if( cfgChannel != 0xff ) {
498 DeviceType::sendPeerEvent(msg,ch);
504 template <
class HalType,
class ChannelType,
int ChannelCount,
class List0Type=List0>
507 ChannelType cdata[ChannelCount];
514 for( uint8_t i=0; i<ChannelCount; ++i ) {
515 this->registerChannel(cdata[i], i+1);