#ifndef radio_h_included #define radio_h_included #include "config.h" #include "display.h" // msgType definitions to identify message and be able to use correcnt structure #define msgType_Clock 'c' /* clock update, sent by master using broadcast */ #define msgType_OfferPairing 'R' /* Request Registration, sent by Master using broadcast; ask clients to register */ #define msgType_RequestPairing 'r' /* Registration message, sent by Client using 1:1 message to master */ #define msgType_ackPairingRequest 'A' #define msgType_TextMessage 'T' // address definitions for special addresses #define MESSAGE_TO_ALL 0xff #define MESSAGE_TO_Master 0x00 #define MESSAGE_FROM_Master MESSAGE_TO_Master // message structures for easy access: struct clockMsg_s { uint8_t msgType; uint8_t to; uint8_t from; char clockName[MAX_CLOCK_NAME_LEN]; uint8_t day; uint8_t hour; uint8_t minute; uint8_t second; uint8_t speed; // msPerModelSecond / 4 --> 0..250 }; struct offerPairing_s { uint8_t msgType; uint8_t to; uint8_t from; char clockName[MAX_CLOCK_NAME_LEN]; uint8_t channel; }; struct requestPairing_s { uint8_t msgType; uint8_t to; uint8_t from; char clientName[MAX_CLIENT_NAME_LEN]; }; struct ackPairing_s { uint8_t msgType; uint8_t to; uint8_t from; char clockName[MAX_CLOCK_NAME_LEN]; char clientName[MAX_CLIENT_NAME_LEN]; uint8_t clientNetworkAddress; // address assigned to client by controller (instead of using names, used as from/to */ }; struct textMessage_s { uint8_t msgType; uint8_t to; uint8_t from; char text[MAX_TEXT_MESSAGE_LEN]; }; class Radio { public: Radio(Display *d, bool _isMaster):display(d), isMaster(_isMaster) { inTX = true; inRX = false; role = inRX; nextRequestToRegisterAnnouncement_ts = 0; nextClockAdvertisement_ts = 0; nextPairingOfferingAnnouncement_ts = 0; timeBetweenClockAdvertisements_ms = DEFAULT_TIME_BETWEEN_CLOCK_ADVERTISEMENTS_ms; timeForClientsToRespond_ms = DEFAULT_TIME_FOR_CLIENTS_TO_RESPOND_ms; timeBetweenPairingOfferingAnnouncements_ms = DEFAULT_TIME_BETWEEN_PAIRING_OFFERINGS_ms; nextSendMessage_ts = 0; clockChannel = DEFAULT_CLOCK_CHANNEL; strncpy(clockName, "defclk", MAX_CLOCK_NAME_LEN); }; void setClockName(const char *_clockName) { strncpy(clockName, _clockName, MAX_CLOCK_NAME_LEN); }; void setClockChannel(uint8_t _channel) { clockChannel = _channel; }; void begin(void); void loop(void); void broadcastClock(int day, int hour, int minute, int second, int msPerModelSecond); void broadcastOfferPairing(const char *clockName, uint8_t channel); void broadcastTextMessage(const char *text); void handleRequestPairing(struct requestPairing_s *request); void ackPairingRequest(char *clientName, uint8_t clientNetworkAddress); void avoidChannelSwitchesFor_ms(unsigned int duration_ms); void listenOnlyFor_ms(unsigned int duration_ms); bool allowedToSendNow(void); private: Display *display; bool isMaster; void switchToSenderRole(void); void switchToReceiverRole(void); bool inTX, inRX, role; char clockName[MAX_CLOCK_NAME_LEN]; void broadcastMessage(void *msg, int len); void broadcastMessageOnChannel(void *msg, int len, uint8_t channel); void broadcastClockAdvertisement(const char *clockName, uint8_t channel); bool checkPairingOffering(void); // returns true, if a message has been sent bool checkClockAdvertisement(void); // returns true, if a message has been sent unsigned long nextClockAdvertisement_ts; unsigned long timeBetweenClockAdvertisements_ms; unsigned long nextPairingOfferingAnnouncement_ts; unsigned long timeBetweenPairingOfferingAnnouncements_ms; unsigned long nextRequestToRegisterAnnouncement_ts; unsigned long timeForClientsToRespond_ms; unsigned long nextSendMessage_ts; uint8_t clockChannel; }; #endif