570 lines
16 KiB
C++
570 lines
16 KiB
C++
// create a simple messageing
|
|
// with the RH_CC110 class. RH_CC110 class does not provide for addressing or
|
|
// reliability, so you should only use RH_CC110 if you do not need the higher
|
|
// level messaging abilities.
|
|
|
|
#include <avr/wdt.h>
|
|
|
|
#define CONFVER "conf00"
|
|
|
|
|
|
#include "config.h"
|
|
#include <EEPROM.h>
|
|
#include "EEPROMAnything.h"
|
|
|
|
#include <avr/wdt.h>
|
|
#include <SPI.h>
|
|
#include <RH_CC110.h>
|
|
|
|
// Singleton instance of the radio driver
|
|
RH_CC110 cc110;
|
|
|
|
// GFSK_Rb1_2Fd5_2 = 0, ///< GFSK, Data Rate: 1.2kBaud, Dev: 5.2kHz, RX BW 58kHz, optimised for sensitivity
|
|
// GFSK_Rb2_4Fd5_2, ///< GFSK, Data Rate: 2.4kBaud, Dev: 5.2kHz, RX BW 58kHz, optimised for sensitivity
|
|
// GFSK_Rb4_8Fd25_4, ///< GFSK, Data Rate: 4.8kBaud, Dev: 25.4kHz, RX BW 100kHz, optimised for sensitivity
|
|
// GFSK_Rb10Fd19, ///< GFSK, Data Rate: 10kBaud, Dev: 19kHz, RX BW 100kHz, optimised for sensitivity
|
|
// GFSK_Rb38_4Fd20, ///< GFSK, Data Rate: 38.4kBaud, Dev: 20kHz, RX BW 100kHz, optimised for sensitivity
|
|
// GFSK_Rb76_8Fd32, ///< GFSK, Data Rate: 76.8kBaud, Dev: 32kHz, RX BW 232kHz, optimised for sensitivity
|
|
// GFSK_Rb100Fd47, ///< GFSK, Data Rate: 100kBaud, Dev: 47kHz, RX BW 325kHz, optimised for sensitivity
|
|
// GFSK_Rb250Fd127, ///< GFSK, Data Rate: 250kBaud, Dev: 127kHz, RX BW 540kHz, optimised for sensitivity
|
|
|
|
|
|
// include the aJSON library
|
|
#include <aJSON.h>
|
|
|
|
// include the JsonRPC library
|
|
#include <JsonRPC.h>
|
|
|
|
// initialize an instance of the JsonRPC library for registering
|
|
// exactly 3 method
|
|
|
|
|
|
#ifdef CLIENT
|
|
JsonRPC rpcclient(5,false); //serial port
|
|
#endif
|
|
#ifdef SERVER
|
|
JsonRPC rpcserver(3,true ); //radio port with compact protocoll
|
|
#endif
|
|
|
|
#ifdef CLIENT
|
|
// initialize a serial json stream for receiving json objects
|
|
// through a serial/USB connection
|
|
aJsonStream stream(&Serial);
|
|
aJsonObject *serialmsg = NULL;
|
|
#endif
|
|
|
|
#ifdef SERVER
|
|
aJsonObject *radiomsg = NULL;
|
|
#endif
|
|
|
|
char confver[7] = CONFVER; // version of configuration saved on eeprom
|
|
|
|
struct config_t // configuration to save and load fron eeprom
|
|
{
|
|
int did; // sample time for mqtt (seconds)
|
|
void save () {
|
|
int p=0; // save to eeprom
|
|
p+=EEPROM_writeAnything(p, confver);
|
|
p+=EEPROM_writeAnything(p, did);
|
|
}
|
|
bool load () { // load from eeprom
|
|
int p=0;
|
|
char ver[7];
|
|
p+=EEPROM_readAnything(p, ver);
|
|
if (strcmp(ver,confver ) == 0){
|
|
p+=EEPROM_readAnything(p, did);
|
|
return true;
|
|
}
|
|
else{
|
|
return false;
|
|
}
|
|
}
|
|
} configuration;
|
|
|
|
//-------------
|
|
|
|
const uint8_t pins [] = {PINS};
|
|
|
|
//-------------
|
|
|
|
void Reboot() {
|
|
IF_SDEBUG(DBGSERIAL.println(F("#Reboot")));
|
|
wdt_enable(WDTO_30MS); while(1) {}
|
|
}
|
|
|
|
#ifdef CLIENT
|
|
int client(aJsonObject* params)
|
|
{
|
|
|
|
uint8_t status=0;
|
|
aJsonObject *newrpc=NULL ;
|
|
newrpc = aJson.createObject();
|
|
//aJson.addStringToObject(newrpc, "m", method);
|
|
|
|
#ifdef TWOWAY
|
|
aJsonObject* id = aJson.getObjectItem(serialmsg, "id");
|
|
if(id){
|
|
aJson.addNumberToObject(newrpc, "i",id -> valueint );
|
|
}
|
|
#endif
|
|
|
|
aJsonObject* mymethod = aJson.detachItemFromObject(serialmsg, "method");
|
|
aJson.addItemToObject(newrpc, "m",mymethod );
|
|
|
|
aJsonObject* myparams = aJson.detachItemFromObject(serialmsg, "params");
|
|
aJson.addItemToObject(newrpc, "p",myparams );
|
|
|
|
char buf[RH_CC110_MAX_MESSAGE_LEN];
|
|
aJson.print(newrpc,buf, sizeof(buf));
|
|
aJson.deleteItem(newrpc);
|
|
|
|
IF_SDEBUG(DBGSERIAL.print(F("#send: ")));
|
|
IF_SDEBUG(DBGSERIAL.println(buf));
|
|
|
|
cc110.send((uint8_t*)buf, strlen(buf));
|
|
cc110.waitPacketSent();
|
|
|
|
#ifdef TWOWAY
|
|
|
|
// Now wait for a reply
|
|
uint8_t len = sizeof(buf);
|
|
|
|
if (cc110.waitAvailableTimeout(3000))
|
|
{
|
|
// Should be a reply message for us now
|
|
if (cc110.recv((uint8_t*)buf, &len))
|
|
{
|
|
IF_SDEBUG(DBGSERIAL.print(F("#got reply: ")));
|
|
IF_SDEBUG(DBGSERIAL.println((char*)buf));
|
|
IF_SDEBUG(DBGSERIAL.print(F("#RSSI: ")));
|
|
IF_SDEBUG(DBGSERIAL.println(cc110.lastRssi(), DEC));
|
|
|
|
#endif
|
|
|
|
//IF_SDEBUG(DBGSERIAL.println("{\"jsonrpc\": \"2.0\", \"result\":true, \"id\": 0}"));
|
|
aJson.addTrueToObject(serialmsg, "result");
|
|
|
|
#ifdef TWOWAY
|
|
|
|
} else {
|
|
IF_SDEBUG(DBGSERIAL.println(F("#recv failed")));
|
|
aJson.addFalseToObject(serialmsg, "result");
|
|
status = 1;
|
|
}
|
|
} else {
|
|
IF_SDEBUG(DBGSERIAL.println(F("#No reply, is cc110_server running?")));
|
|
aJson.addFalseToObject(serialmsg, "result");
|
|
status = 1;
|
|
}
|
|
|
|
#endif
|
|
char serialbuf[SERIALBUFFERSIZE];
|
|
|
|
aJson.print(serialmsg,serialbuf, sizeof(serialbuf));
|
|
Serial.println(serialbuf);
|
|
|
|
return status;
|
|
|
|
}
|
|
#endif
|
|
|
|
#ifdef CLIENT
|
|
int setdid(aJsonObject* params)
|
|
{
|
|
uint8_t status=1;
|
|
aJson.deleteItemFromObject(serialmsg, "method");
|
|
|
|
aJsonObject* myparams = aJson.detachItemFromObject(serialmsg, "params");
|
|
aJsonObject* didParam = aJson.getObjectItem(myparams, "d");
|
|
if (didParam){
|
|
int did = didParam -> valueint;
|
|
configuration.did=did;
|
|
|
|
aJson.addTrueToObject(serialmsg, "result");
|
|
char buf[SERIALBUFFERSIZE];
|
|
aJson.print(serialmsg,buf, sizeof(buf));
|
|
Serial.println(buf);
|
|
|
|
status= 0;
|
|
}
|
|
aJson.deleteItem(params);
|
|
return status;
|
|
}
|
|
|
|
int save(aJsonObject* params)
|
|
{
|
|
uint8_t status=1;
|
|
aJson.deleteItemFromObject(serialmsg, "method");
|
|
|
|
aJsonObject* myparams = aJson.detachItemFromObject(serialmsg, "params");
|
|
|
|
aJsonObject* saveParam = aJson.getObjectItem(myparams, "eeprom");
|
|
if (saveParam){
|
|
bool eeprom = saveParam -> valuebool;
|
|
|
|
if (eeprom) configuration.save();
|
|
|
|
aJson.addTrueToObject(serialmsg, "result");
|
|
char buf[SERIALBUFFERSIZE];
|
|
aJson.print(serialmsg,buf, sizeof(buf));
|
|
Serial.println(buf);
|
|
|
|
status = 0;
|
|
}
|
|
|
|
aJson.deleteItem(params);
|
|
return status;
|
|
|
|
}
|
|
#endif
|
|
#ifdef SERVER
|
|
int changedidserver(aJsonObject* params)
|
|
{
|
|
aJsonObject* olddidParam = aJson.getObjectItem(params, "olddid");
|
|
if (olddidParam){
|
|
int olddid = olddidParam -> valueint;
|
|
if (olddid == configuration.did || olddid == 0 ){
|
|
|
|
aJsonObject* didParam = aJson.getObjectItem(params, "d");
|
|
if (didParam){
|
|
int did = didParam -> valueint;
|
|
configuration.did=did;
|
|
|
|
aJson.deleteItemFromObject(radiomsg, "m");
|
|
aJson.deleteItemFromObject(radiomsg, "p");
|
|
aJson.addTrueToObject(radiomsg, "r");
|
|
|
|
}
|
|
}
|
|
}
|
|
//aJson.deleteItem(params);
|
|
return 0;
|
|
}
|
|
|
|
int saveserver(aJsonObject* params)
|
|
{
|
|
|
|
aJsonObject* didParam = aJson.getObjectItem(params, "d");
|
|
if (didParam){
|
|
int did = didParam -> valueint;
|
|
if (did == configuration.did || did == 0 ){ //my did or broadcast
|
|
|
|
aJsonObject* saveParam = aJson.getObjectItem(params, "eeprom");
|
|
if (saveParam){
|
|
boolean eeprom = saveParam -> valuebool;
|
|
|
|
if (eeprom) configuration.save();
|
|
aJson.deleteItemFromObject(radiomsg, "m");
|
|
aJson.deleteItemFromObject(radiomsg, "p");
|
|
aJson.addTrueToObject(radiomsg, "r");
|
|
|
|
}
|
|
}
|
|
}
|
|
//aJson.deleteItem(params);
|
|
return 0;
|
|
}
|
|
|
|
int singleserver(aJsonObject* params)
|
|
{
|
|
//{"jsonrpc":"2.0","method":"single","params":{"d":1,"u":1,"o":true},"id":0}
|
|
|
|
aJsonObject* didParam = aJson.getObjectItem(params, "d");
|
|
if (didParam){
|
|
int did = didParam -> valueint;
|
|
if (did == configuration.did || did == 0 ){ //my did or broadcast
|
|
|
|
aJsonObject* dstunitParam = aJson.getObjectItem(params, "u");
|
|
if (dstunitParam){
|
|
int dstunit = dstunitParam -> valueint;
|
|
|
|
if (dstunit >= 0 && dstunit < sizeof(pins)/sizeof(*pins)){
|
|
aJsonObject* onoffParam = aJson.getObjectItem(params, "o");
|
|
if (onoffParam){
|
|
boolean onoff = onoffParam -> valuebool;
|
|
IF_SDEBUG(DBGSERIAL.print(F("#did: ")));
|
|
IF_SDEBUG(DBGSERIAL.print(did));
|
|
IF_SDEBUG(DBGSERIAL.print(F(" dstunit: ")));
|
|
IF_SDEBUG(DBGSERIAL.print(dstunit));
|
|
IF_SDEBUG(DBGSERIAL.print(F(" onoff: ")));
|
|
IF_SDEBUG(DBGSERIAL.println(onoff));
|
|
|
|
digitalWrite(pins[dstunit], ! onoff);
|
|
|
|
aJson.deleteItemFromObject(radiomsg, "m");
|
|
aJson.deleteItemFromObject(radiomsg, "p");
|
|
aJson.addTrueToObject(radiomsg, "r");
|
|
|
|
}else{
|
|
IF_SDEBUG(DBGSERIAL.println(F("#no onoff")));
|
|
}
|
|
}else{
|
|
IF_SDEBUG(DBGSERIAL.println(F("#wrong dstunit")));
|
|
}
|
|
}else{
|
|
IF_SDEBUG(DBGSERIAL.println(F("#no dstunit")));
|
|
}
|
|
}else{
|
|
IF_SDEBUG(DBGSERIAL.println(F("#not for me")));
|
|
}
|
|
}else{
|
|
IF_SDEBUG(DBGSERIAL.println(F("#no did")));
|
|
}
|
|
//IF_SDEBUG(DBGSERIAL.println(F("{\"result\": \"OK\"}"));
|
|
//aJson.deleteItem(params);
|
|
return 0;
|
|
}
|
|
#endif
|
|
void setup()
|
|
{
|
|
|
|
/*
|
|
Nel caso di un chip in standalone senza bootloader, la prima
|
|
istruzione che è bene mettere nel setup() è sempre la disattivazione
|
|
del Watchdog stesso: il Watchdog, infatti, resta attivo dopo il
|
|
reset e, se non disabilitato, esso può provare il reset perpetuo del
|
|
microcontrollore
|
|
*/
|
|
wdt_disable();
|
|
|
|
wdt_enable(WDTO_8S);
|
|
|
|
IF_SDEBUG(DBGSERIAL.begin(SERIALBAUDRATE));
|
|
Serial.begin(SERIALBAUDRATE);
|
|
while (!Serial); // wait for serial port to connect. Needed for native USB
|
|
Serial.println(F("#Started: "VERSION));
|
|
#ifdef TWOWAY
|
|
Serial.println(F("#Twovay: "TWOWAY));
|
|
#endif
|
|
#ifdef CLIENT
|
|
Serial.println(F("#Client: "CLIENT));
|
|
#endif
|
|
#ifdef SERVER
|
|
Serial.println(F("#Server: "SERVER));
|
|
#endif
|
|
|
|
if (configuration.load()){
|
|
IF_SDEBUG(DBGSERIAL.println(F("#Configuration loaded")));
|
|
IF_SDEBUG(DBGSERIAL.print(F("#did:")));
|
|
IF_SDEBUG(DBGSERIAL.println(configuration.did));
|
|
} else {
|
|
IF_SDEBUG(DBGSERIAL.println(F("#Configuration not loaded")));
|
|
}
|
|
|
|
// register the local single method
|
|
#ifdef SERVER
|
|
// Radio port
|
|
rpcserver.registerMethod("single", &singleserver);
|
|
rpcserver.registerMethod("changedid", &changedidserver);
|
|
rpcserver.registerMethod("remotesave",&saveserver);
|
|
#endif
|
|
|
|
#ifdef CLIENT
|
|
// Serial port
|
|
rpcclient.registerMethod("single", &client);
|
|
rpcclient.registerMethod("changedid", &client);
|
|
rpcclient.registerMethod("remotesave",&client);
|
|
rpcclient.registerMethod("setdid", &setdid);
|
|
rpcclient.registerMethod("save", &save);
|
|
#endif
|
|
|
|
// CC110L may be equipped with either 26 or 27MHz crystals. You MUST
|
|
// tell the driver if a 27MHz crystal is installed for the correct configuration to
|
|
// occur. Failure to correctly set this flag will cause incorrect frequency and modulation
|
|
// characteristics to be used. You can call this function, or pass it to the constructor
|
|
//cc110.setIs27MHz(true); // Anaren 430BOOST-CC110L Air BoosterPack test boards have 27MHz
|
|
|
|
if (!cc110.init()){
|
|
IF_SDEBUG(DBGSERIAL.println(F("init failed")));
|
|
Reboot();
|
|
}
|
|
// After init(), the following default values apply:
|
|
// TxPower: TransmitPower5dBm
|
|
// Frequency: 915.0
|
|
// Modulation: GFSK_Rb1_2Fd5_2 (GFSK, Data Rate: 1.2kBaud, Dev: 5.2kHz, RX BW 58kHz, optimised for sensitivity)
|
|
// Sync Words: 0xd3, 0x91
|
|
// But you can change them:
|
|
// cc110.setTxPower(RH_CC110::TransmitPowerM30dBm);
|
|
// cc110.setModemConfig(RH_CC110::GFSK_Rb250Fd127);
|
|
//cc110.setFrequency(928.0);
|
|
|
|
/*
|
|
Canale Frequenza (MHz) Canale Frequenza (MHz) Canale Frequenza (MHz)
|
|
1 433.075 24 433.650 47 434.225
|
|
2 433.100 25 433.675 48 434.250
|
|
3 433.125 26 433.700 49 434.275
|
|
4 433.150 27 433.725 50 434.300
|
|
5 433.175 28 433.750 51 434.325
|
|
6 433.200 29 433.775 52 434.350
|
|
7 433.225 30 433.800 53 434.375
|
|
8 433.250 31 433.825 54 434.400
|
|
9 433.275 32 433.850 55 434.425
|
|
10 433.300 33 433.875 56 434.450
|
|
11 433.325 34 433.900 57 434.475
|
|
12 433.350 35 433.925 58 434.500
|
|
13 433.375 36 433.950 59 434.525
|
|
14 433.400 37 433.975 60 434.550
|
|
15 433.425 38 434.000 61 434.575
|
|
16 433.450 39 434.025 62 434.600
|
|
17 433.475 40 434.050 63 434.625
|
|
18 433.500 41 434.075 64 434.650
|
|
19 433.525 42 434.100 65 434.675
|
|
20 433.550 43 434.125 66 434.700
|
|
21 433.575 44 434.150 67 434.725
|
|
22 433.600 45 434.175 68 434.750
|
|
23 433.625 46 434.200 69 434.775
|
|
*/
|
|
|
|
cc110.setTxPower(RH_CC110::TransmitPower0dBm);
|
|
//cc110.setModemConfig(RH_CC110::GFSK_Rb4_8Fd25_4); // Giacomo
|
|
cc110.setModemConfig(RH_CC110::GFSK_Rb100Fd47); // Pat1
|
|
|
|
// For 26MHz crystals
|
|
//PROGMEM static const RH_CC110::ModemConfig GFSK_R1_2Fd25_4 =
|
|
static const RH_CC110::ModemConfig GFSK_R1_2Fd25_4 =
|
|
// 0B 0C 10 11 12 15 19 1A 1B 1C 1D 21 22 23 24 25 26 2C 2D 2E
|
|
{0x06, 0x00, 0xC5, 0x83, 0x13, 0x40, 0x16, 0x6c, 0x43, 0x40, 0x91, 0x56, 0x10, 0xe9, 0x2a, 0x00, 0x1f, 0x81, 0x35, 0x09}; // GFSK_R1_2Fd47 GFSK, Data Rate: 1.2kBaud, Dev: 47kHz, RX BW 325kHz, optimised for sensitivity
|
|
//{0x06, 0x00, 0xc7, 0x83, 0x13, 0x40, 0x16, 0x6c, 0x43, 0x40, 0x91, 0x56, 0x10, 0xe9, 0x2a, 0x00, 0x1f, 0x81, 0x35, 0x09}; // GFSK_Rb4_8Fd25_4
|
|
|
|
//cc110.setModemRegisters(&GFSK_R1_2Fd25_4);
|
|
|
|
cc110.setFrequency(434.0+FREQCORR);
|
|
|
|
|
|
for (int dstunit=0 ;dstunit < sizeof(pins)/sizeof(*pins); dstunit++)
|
|
{
|
|
pinMode(pins[dstunit], OUTPUT);
|
|
digitalWrite(pins[dstunit], 1);
|
|
}
|
|
|
|
#ifdef CLIENT
|
|
if (stream.available()) {
|
|
// skip any accidental whitespace like newlines
|
|
stream.skip();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
#ifdef CLIENT
|
|
void mgr_serial(){
|
|
unsigned int err;
|
|
|
|
if (stream.available()) {
|
|
|
|
serialmsg = aJson.parse(&stream);
|
|
if (serialmsg){
|
|
IF_SDEBUG(DBGSERIAL.print(F("#rpc.processMessage:")));
|
|
char serialbuf[SERIALBUFFERSIZE];
|
|
aJson.print(serialmsg, serialbuf, sizeof(serialbuf));
|
|
IF_SDEBUG(DBGSERIAL.println(serialbuf));
|
|
|
|
err=rpcclient.processMessage(serialmsg);
|
|
IF_SDEBUG(DBGSERIAL.print(F("#rpcclient.processMessage return status:")));
|
|
IF_SDEBUG(DBGSERIAL.println(err));
|
|
if (!err){
|
|
aJson.deleteItem(serialmsg);
|
|
}else{
|
|
err = 1;
|
|
}
|
|
|
|
}else{
|
|
IF_SDEBUG(DBGSERIAL.println(F("#skip wrong message")));
|
|
err = 2;
|
|
if (stream.available()) {
|
|
stream.flush();
|
|
}
|
|
}
|
|
|
|
if (err == 1){
|
|
aJsonObject *result = aJson.createObject();
|
|
aJson.addItemToObject(serialmsg, "error", result);
|
|
aJson.addNumberToObject(result, "code", E_INTERNAL_ERROR);
|
|
aJson.addStringToObject(result,"message", strerror(E_INTERNAL_ERROR));
|
|
|
|
/*
|
|
if (!rpcid || !msg){
|
|
IF_SDEBUG(IF_SDEBUG(DBGSERIAL.println(F("#add null id in response"))));
|
|
aJson.addNullToObject(serialmsg, "id");
|
|
} else {
|
|
IF_SDEBUG(IF_SDEBUG(DBGSERIAL.println(F("#add id in response"))));
|
|
aJson.addNumberToObject(serialmsg, "id", rpcid->valueint);
|
|
}
|
|
*/
|
|
|
|
char serialbuf[SERIALBUFFERSIZE];
|
|
|
|
aJson.print(serialmsg,serialbuf, sizeof(serialbuf));
|
|
Serial.println(serialbuf);
|
|
aJson.deleteItem(serialmsg);
|
|
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#ifdef SERVER
|
|
void mgr_radio(){
|
|
unsigned int err;
|
|
if (cc110.available())
|
|
{
|
|
// Should be a message for us now
|
|
uint8_t buf[RH_CC110_MAX_MESSAGE_LEN+1];
|
|
uint8_t len = RH_CC110_MAX_MESSAGE_LEN;
|
|
if (cc110.recv(buf, &len))
|
|
{
|
|
buf[len]=NULL; // terminate the string
|
|
//RH_CC110::printBuffer("#request: ", buf, len);
|
|
IF_SDEBUG(DBGSERIAL.print(F("#got request: ")));
|
|
IF_SDEBUG(DBGSERIAL.println((char*)buf));
|
|
IF_SDEBUG(DBGSERIAL.print(F("#RSSI: ")));
|
|
IF_SDEBUG(DBGSERIAL.println(cc110.lastRssi(), DEC));
|
|
|
|
radiomsg = aJson.parse((char*)buf);
|
|
|
|
if (radiomsg){
|
|
err=rpcserver.processMessage(radiomsg);
|
|
IF_SDEBUG(DBGSERIAL.print(F("#rpcserver.processMessage return status:")));
|
|
IF_SDEBUG(DBGSERIAL.println(err));
|
|
if (!err) {
|
|
#ifdef TWOWAY
|
|
|
|
// Send a reply
|
|
// "{\"jsonrpc\": \"2.0\", \"result\":true, \"id\": 0}"
|
|
|
|
aJson.print(radiomsg, (char*)buf, sizeof(buf));
|
|
IF_SDEBUG(DBGSERIAL.print(F("#Send: ")));
|
|
IF_SDEBUG(DBGSERIAL.println((char*)buf));
|
|
cc110.send(buf, len);
|
|
cc110.waitPacketSent();
|
|
IF_SDEBUG(DBGSERIAL.println(F("#Sent a reply")));
|
|
#endif
|
|
|
|
aJson.deleteItem(radiomsg);
|
|
}else{
|
|
err = 1;
|
|
aJson.deleteItem(radiomsg);
|
|
}
|
|
}else{
|
|
IF_SDEBUG(DBGSERIAL.println(F("#skip wrong message")));
|
|
err = 2;
|
|
}
|
|
} else {
|
|
IF_SDEBUG(DBGSERIAL.println(F("recv failed")));
|
|
err = 3;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
void loop()
|
|
{
|
|
wdt_reset();
|
|
#ifdef CLIENT
|
|
mgr_serial();
|
|
#endif
|
|
#ifdef SERVER
|
|
wdt_reset();
|
|
mgr_radio();
|
|
#endif
|
|
}
|